/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25331 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 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