/[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

Annotation of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide 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 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 dpavlin 2 *
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 dpavlin 44 * $Id: main.c,v 1.311 2007/06/28 14:58:38 debug Exp $
29 dpavlin 2 */
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 dpavlin 26 #include "debugger.h"
41 dpavlin 2 #include "device.h"
42     #include "diskimage.h"
43     #include "emul.h"
44     #include "machine.h"
45     #include "misc.h"
46 dpavlin 24 #include "settings.h"
47 dpavlin 32 #include "timer.h"
48 dpavlin 42 #include "useremul.h"
49 dpavlin 2
50    
51 dpavlin 42 extern int single_step;
52 dpavlin 2 extern int force_debugger_at_exit;
53    
54     extern int optind;
55     extern char *optarg;
56    
57 dpavlin 24 struct settings *global_settings;
58    
59 dpavlin 2 int extra_argc;
60     char **extra_argv;
61     char *progname;
62    
63 dpavlin 34 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
64 dpavlin 44 static int skip_srandom_call = 0;
65 dpavlin 2
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 dpavlin 44 printf("GXemul "VERSION" Copyright (C) 2003-2007 Anders Gavare\n");
200 dpavlin 2 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 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
206 dpavlin 2 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 dpavlin 6 printf(" b specifies that this is the boot"
228 dpavlin 2 " device\n");
229 dpavlin 6 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 dpavlin 34 printf(" oOFS; set base offset to OFS (for ISO9660"
236     " filesystems)\n");
237 dpavlin 6 printf(" r read-only (don't allow changes to the"
238 dpavlin 2 " file)\n");
239 dpavlin 6 printf(" s SCSI\n");
240     printf(" t tape\n");
241 dpavlin 38 printf(" V add an overlay\n");
242 dpavlin 6 printf(" 0-7 force a specific ID\n");
243 dpavlin 32 printf(" -I hz set the main cpu frequency to hz (not used by "
244 dpavlin 34 "all combinations\n of machines and guest OSes)\n");
245 dpavlin 2 printf(" -i display each instruction as it is executed\n");
246 dpavlin 28 printf(" -J disable dyntrans instruction combinations\n");
247 dpavlin 24 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 dpavlin 2 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 dpavlin 24 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 dpavlin 2 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 dpavlin 28 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 dpavlin 34 printf(" -T halt on non-existant memory accesses\n");
286 dpavlin 2 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 dpavlin 22 "(default is on when\n using configuration files or"
292     " when X11 is used, off otherwise)\n");
293 dpavlin 2 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 dpavlin 22 printf(" -c cmd add cmd as a command to run before starting "
307     "the simulation\n");
308 dpavlin 32 printf(" -D skip the srandom call at startup\n");
309 dpavlin 2 printf(" -H display a list of possible CPU and "
310     "machine types\n");
311     printf(" -h display this help message\n");
312 dpavlin 34 printf(" -k n set dyntrans translation caches to n MB (default"
313     " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
314 dpavlin 2 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 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
329 dpavlin 42 "\nExamples:\n"
330 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
331     " 0xbfc00000:0x100:rom.bin for an image with "
332 dpavlin 2 "0x100 bytes header\n"
333 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
334 dpavlin 42 "start with pc=0xbfc00884\n\n");
335 dpavlin 2 }
336    
337    
338     /*
339     * get_cmd_args():
340     *
341     * Reads command line arguments.
342     */
343 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
344     char ***diskimagesp, int *n_diskimagesp)
345 dpavlin 2 {
346     int ch, res, using_switch_d = 0, using_switch_Z = 0;
347 dpavlin 24 int using_switch_e = 0, using_switch_E = 0;
348 dpavlin 2 char *type = NULL, *subtype = NULL;
349     int n_cpus_set = 0;
350     int msopts = 0; /* Machine-specific options used */
351 dpavlin 44 struct machine *m = emul_add_machine(emul, NULL);
352 dpavlin 2
353 dpavlin 24 char *opts =
354 dpavlin 44 "C:c:Dd:E:e:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtUu:VvW:"
355 dpavlin 24 #ifdef WITH_X11
356     "XxY:"
357     #endif
358     "Z:z:";
359    
360     while ((ch = getopt(argc, argv, opts)) != -1) {
361 dpavlin 2 switch (ch) {
362     case 'C':
363 dpavlin 42 CHECK_ALLOCATION(m->cpu_name = strdup(optarg));
364 dpavlin 2 msopts = 1;
365     break;
366 dpavlin 22 case 'c':
367     emul->n_debugger_cmds ++;
368 dpavlin 42 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 dpavlin 22 break;
374 dpavlin 2 case 'D':
375 dpavlin 32 skip_srandom_call = 1;
376 dpavlin 2 break;
377     case 'd':
378 dpavlin 4 /* diskimage_add() is called further down */
379     (*n_diskimagesp) ++;
380 dpavlin 42 CHECK_ALLOCATION( (*diskimagesp) =
381     realloc(*diskimagesp,
382     sizeof(char *) * (*n_diskimagesp)) );
383     CHECK_ALLOCATION( (*diskimagesp)[(*n_diskimagesp) - 1] =
384     strdup(optarg) );
385 dpavlin 2 using_switch_d = 1;
386     msopts = 1;
387     break;
388     case 'E':
389 dpavlin 24 if (using_switch_E ++ > 0) {
390     fprintf(stderr, "-E already used.\n");
391     exit(1);
392     }
393 dpavlin 2 type = optarg;
394     msopts = 1;
395     break;
396     case 'e':
397 dpavlin 24 if (using_switch_e ++ > 0) {
398     fprintf(stderr, "-e already used.\n");
399     exit(1);
400     }
401 dpavlin 2 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 dpavlin 28 m->allow_instruction_combinations = 0;
420 dpavlin 2 msopts = 1;
421     break;
422     case 'j':
423 dpavlin 42 CHECK_ALLOCATION(m->boot_kernel_filename =
424     strdup(optarg));
425 dpavlin 2 msopts = 1;
426     break;
427 dpavlin 34 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 dpavlin 2 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 dpavlin 42 CHECK_ALLOCATION(m->boot_string_argument =
457     strdup(optarg));
458 dpavlin 2 msopts = 1;
459     break;
460     case 'p':
461 dpavlin 42 machine_add_breakpoint_string(m, optarg);
462 dpavlin 2 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 dpavlin 28 case 's':
484     machine_statistics_init(m, optarg);
485     msopts = 1;
486     break;
487 dpavlin 34 case 'T':
488     m->halt_on_nonexistant_memaccess = 1;
489     msopts = 1;
490     break;
491 dpavlin 2 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 dpavlin 42 CHECK_ALLOCATION(m->userland_emul = strdup(optarg));
501 dpavlin 2 m->machine_type = MACHINE_USERLAND;
502     msopts = 1;
503     break;
504     case 'V':
505 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
506 dpavlin 2 break;
507     case 'v':
508     verbose ++;
509     break;
510     case 'W':
511     internal_w(optarg);
512     exit(0);
513     case 'X':
514 dpavlin 42 m->x11_md.in_use = 1;
515 dpavlin 2 msopts = 1;
516 dpavlin 22 /* FALL-THROUGH */
517 dpavlin 2 case 'x':
518     console_allow_slaves(1);
519     break;
520     case 'Y':
521 dpavlin 42 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 dpavlin 20 }
526 dpavlin 42 if (m->x11_md.scaledown < 1) {
527 dpavlin 4 fprintf(stderr, "Invalid scaledown value.\n");
528     exit(1);
529     }
530 dpavlin 2 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 dpavlin 42 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 dpavlin 2 msopts = 1;
545     break;
546     default:
547 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
548     "line options.\n", progname);
549 dpavlin 2 exit(1);
550     }
551     }
552    
553 dpavlin 12 if (type != NULL || subtype != NULL) {
554     if (type == NULL)
555     type = "";
556 dpavlin 2 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 dpavlin 12 /* -i and -r are pretty verbose: */
579 dpavlin 2
580     if (m->instruction_trace && !verbose) {
581 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
582     " of -i\n", quiet_mode? "turning off -q and " : "");
583 dpavlin 2 verbose = 1;
584     quiet_mode = 0;
585     }
586    
587     if (m->register_dump && !verbose) {
588 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
589     " of -r\n", quiet_mode? "turning off -q and " : "");
590 dpavlin 2 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 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
600     * then try to boot from disk.
601 dpavlin 2 */
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 dpavlin 42 CHECK_ALLOCATION(m->boot_kernel_filename = strdup(s2));
629 dpavlin 2 }
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 dpavlin 42 if (!using_switch_Z && !m->x11_md.in_use)
637 dpavlin 2 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 dpavlin 32 /* 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 dpavlin 44 struct emul *emul;
662     int config_file = 0;
663    
664 dpavlin 4 char **diskimages = NULL;
665     int n_diskimages = 0;
666 dpavlin 2 int i;
667    
668 dpavlin 44
669 dpavlin 2 progname = argv[0];
670    
671 dpavlin 32
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 dpavlin 24 global_settings = settings_new();
679    
680 dpavlin 32 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 dpavlin 34 /* Read-only settings: */
690 dpavlin 24 settings_add(global_settings, "single_step", 0,
691     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
692 dpavlin 34
693     /* Read/write settings: */
694 dpavlin 24 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 dpavlin 2 console_init();
704     cpu_init();
705     device_init();
706     machine_init();
707 dpavlin 32 timer_init();
708 dpavlin 2 useremul_init();
709    
710 dpavlin 44 /* 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 dpavlin 2
715 dpavlin 44 get_cmd_args(argc, argv, emul, &diskimages, &n_diskimages);
716 dpavlin 2
717 dpavlin 32 if (!skip_srandom_call) {
718     struct timeval tv;
719     gettimeofday(&tv, NULL);
720     srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
721 dpavlin 2 }
722    
723     /* Print startup message: */
724 dpavlin 44 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 dpavlin 2
728 dpavlin 44 /* Simple initialization, from command line arguments: */
729     if (emul->machines[0]->machine_type != MACHINE_NONE) {
730 dpavlin 4 for (i=0; i<n_diskimages; i++)
731 dpavlin 44 diskimage_add(emul->machines[0], diskimages[i]);
732 dpavlin 2
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 dpavlin 44 emul_simple_init(emul);
746 dpavlin 2 }
747    
748 dpavlin 44 /* Initialize an emulation from a config file: */
749 dpavlin 2 for (i=1; i<argc; i++) {
750     if (argv[i][0] == '@') {
751     char *s = argv[i] + 1;
752 dpavlin 44
753     if (config_file) {
754     fprintf(stderr, "More than one configuration "
755     "file cannot be used.\n");
756     exit(1);
757 dpavlin 2 }
758    
759 dpavlin 44 if (strlen(s) == 0 && i+1 < argc && *argv[i+1] != '@')
760     s = argv[++i];
761    
762     /* Always allow slave xterms: */
763 dpavlin 2 console_allow_slaves(1);
764 dpavlin 22
765 dpavlin 44 /* Destroy the temporary emul, since it will
766 dpavlin 32 be overwritten: */
767 dpavlin 44 if (emul != NULL) {
768     emul_destroy(emul);
769     settings_remove(global_settings, "emul");
770     emul = NULL;
771 dpavlin 32 }
772    
773 dpavlin 44 emul = emul_create_from_configfile(s);
774 dpavlin 32
775 dpavlin 44 settings_add(global_settings, "emul", 1,
776     SETTINGS_TYPE_SUBSETTINGS, 0, emul->settings);
777    
778     config_file = 1;
779 dpavlin 2 }
780     }
781    
782 dpavlin 44 if (emul->n_machines == 0) {
783 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
784 dpavlin 12 "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 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
787     "image.\n", progname);
788 dpavlin 2 exit(1);
789     }
790    
791     device_set_exit_on_error(0);
792 dpavlin 22 console_warn_if_slaves_are_needed(1);
793 dpavlin 2
794 dpavlin 32
795 dpavlin 44 /* Run the emulation: */
796     emul_run(emul);
797 dpavlin 2
798 dpavlin 32
799     /*
800     * Deinitialize everything:
801     */
802    
803     console_deinit();
804    
805 dpavlin 44 emul_destroy(emul);
806 dpavlin 32
807     settings_remove_all(global_settings);
808 dpavlin 24 settings_destroy(global_settings);
809    
810 dpavlin 2 return 0;
811     }
812    

  ViewVC Help
Powered by ViewVC 1.1.26