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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (hide annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 25389 byte(s)
0.4.4
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 34 * $Id: main.c,v 1.293 2007/02/05 16:49:05 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 2
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 dpavlin 24 struct settings *global_settings;
57    
58 dpavlin 2 int extra_argc;
59     char **extra_argv;
60     char *progname;
61    
62 dpavlin 34 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
63     int native_code_translation_enabled = 0;
64 dpavlin 32 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     printf("GXemul");
200     #ifdef VERSION
201 dpavlin 28 printf(" " VERSION);
202 dpavlin 2 #endif
203 dpavlin 34 printf(" Copyright (C) 2003-2007 Anders Gavare\n");
204 dpavlin 2 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 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
210 dpavlin 24 #ifdef UNSTABLE_DEVEL
211 dpavlin 2 printf(" or %s [userland, other, and general options] file "
212     "[args ...]\n", progname);
213 dpavlin 24 #endif
214 dpavlin 2
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 dpavlin 6 printf(" b specifies that this is the boot"
234 dpavlin 2 " device\n");
235 dpavlin 6 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 dpavlin 34 printf(" oOFS; set base offset to OFS (for ISO9660"
242     " filesystems)\n");
243 dpavlin 6 printf(" r read-only (don't allow changes to the"
244 dpavlin 2 " file)\n");
245 dpavlin 6 printf(" s SCSI\n");
246     printf(" t tape\n");
247     printf(" 0-7 force a specific ID\n");
248 dpavlin 24 printf(" -G port listen to gdb remote connections on this port\n");
249 dpavlin 32 printf(" -I hz set the main cpu frequency to hz (not used by "
250 dpavlin 34 "all combinations\n of machines and guest OSes)\n");
251 dpavlin 2 printf(" -i display each instruction as it is executed\n");
252 dpavlin 28 printf(" -J disable dyntrans instruction combinations\n");
253 dpavlin 24 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 dpavlin 2 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 dpavlin 24 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 dpavlin 2 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 dpavlin 28 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 dpavlin 34 printf(" -T halt on non-existant memory accesses\n");
292 dpavlin 2 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 dpavlin 22 "(default is on when\n using configuration files or"
298     " when X11 is used, off otherwise)\n");
299 dpavlin 2 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 dpavlin 24 #ifdef UNSTABLE_DEVEL
308 dpavlin 2 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 dpavlin 24 #endif
312 dpavlin 2
313     printf("\nGeneral options:\n");
314 dpavlin 34 #ifdef UNSTABLE_DEVEL
315     printf(" -b enable native code generation\n");
316     printf(" -B disable native code generation\n");
317     #endif
318 dpavlin 22 printf(" -c cmd add cmd as a command to run before starting "
319     "the simulation\n");
320 dpavlin 32 printf(" -D skip the srandom call at startup\n");
321 dpavlin 2 printf(" -H display a list of possible CPU and "
322     "machine types\n");
323     printf(" -h display this help message\n");
324 dpavlin 34 printf(" -k n set dyntrans translation caches to n MB (default"
325     " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
326 dpavlin 2 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 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
341 dpavlin 2 "Examples:\n"
342 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
343     " 0xbfc00000:0x100:rom.bin for an image with "
344 dpavlin 2 "0x100 bytes header\n"
345 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
346 dpavlin 2 "start with pc=0xbfc00884\n");
347     }
348    
349    
350     /*
351     * get_cmd_args():
352     *
353     * Reads command line arguments.
354     */
355 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
356     char ***diskimagesp, int *n_diskimagesp)
357 dpavlin 2 {
358     int ch, res, using_switch_d = 0, using_switch_Z = 0;
359 dpavlin 24 int using_switch_e = 0, using_switch_E = 0;
360 dpavlin 2 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 dpavlin 24 char *opts =
366     #ifdef UNSTABLE_DEVEL
367 dpavlin 34 "bB"
368     #endif
369     "C:c:Dd:E:e:G:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtU"
370     #ifdef UNSTABLE_DEVEL
371 dpavlin 24 "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 dpavlin 2 switch (ch) {
381 dpavlin 34 #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 dpavlin 2 case 'C':
395     m->cpu_name = strdup(optarg);
396     msopts = 1;
397     break;
398 dpavlin 22 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 dpavlin 2 case 'D':
410 dpavlin 32 skip_srandom_call = 1;
411 dpavlin 2 break;
412     case 'd':
413 dpavlin 4 /* 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 dpavlin 2 using_switch_d = 1;
423     msopts = 1;
424     break;
425     case 'E':
426 dpavlin 24 if (using_switch_E ++ > 0) {
427     fprintf(stderr, "-E already used.\n");
428     exit(1);
429     }
430 dpavlin 2 type = optarg;
431     msopts = 1;
432     break;
433     case 'e':
434 dpavlin 24 if (using_switch_e ++ > 0) {
435     fprintf(stderr, "-e already used.\n");
436     exit(1);
437     }
438 dpavlin 2 subtype = optarg;
439     msopts = 1;
440     break;
441 dpavlin 24 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 dpavlin 26 /* Note: implicit -V */
449     single_step = ENTER_SINGLE_STEPPING;
450 dpavlin 24 msopts = 1;
451     break;
452 dpavlin 2 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 dpavlin 28 m->allow_instruction_combinations = 0;
468 dpavlin 2 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 dpavlin 34 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 dpavlin 2 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 dpavlin 28 case 's':
548     machine_statistics_init(m, optarg);
549 dpavlin 34 native_code_translation_enabled = 0;
550 dpavlin 28 msopts = 1;
551     break;
552 dpavlin 34 case 'T':
553     m->halt_on_nonexistant_memaccess = 1;
554     msopts = 1;
555     break;
556 dpavlin 2 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 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
575 dpavlin 2 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 dpavlin 22 /* FALL-THROUGH */
586 dpavlin 2 case 'x':
587     console_allow_slaves(1);
588     break;
589     case 'Y':
590     m->x11_scaledown = atoi(optarg);
591 dpavlin 20 if (m->x11_scaledown < -1) {
592     m->x11_scaleup = - m->x11_scaledown;
593     m->x11_scaledown = 1;
594     }
595 dpavlin 4 if (m->x11_scaledown < 1) {
596     fprintf(stderr, "Invalid scaledown value.\n");
597     exit(1);
598     }
599 dpavlin 2 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 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
626     "line options.\n", progname);
627 dpavlin 2 exit(1);
628     }
629     }
630    
631 dpavlin 12 if (type != NULL || subtype != NULL) {
632     if (type == NULL)
633     type = "";
634 dpavlin 2 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 dpavlin 12 /* -i and -r are pretty verbose: */
657 dpavlin 2
658     if (m->instruction_trace && !verbose) {
659 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
660     " of -i\n", quiet_mode? "turning off -q and " : "");
661 dpavlin 2 verbose = 1;
662     quiet_mode = 0;
663     }
664    
665     if (m->register_dump && !verbose) {
666 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
667     " of -r\n", quiet_mode? "turning off -q and " : "");
668 dpavlin 2 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 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
678     * then try to boot from disk.
679 dpavlin 2 */
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 dpavlin 32 /* 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 dpavlin 2 struct emul **emuls;
744 dpavlin 4 char **diskimages = NULL;
745     int n_diskimages = 0;
746 dpavlin 2 int n_emuls;
747     int i;
748    
749 dpavlin 32
750 dpavlin 34 #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 dpavlin 2 progname = argv[0];
762    
763 dpavlin 32
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 dpavlin 24 global_settings = settings_new();
771    
772 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 24 settings_add(global_settings, "single_step", 0,
786     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
787 dpavlin 34
788     /* Read/write settings: */
789 dpavlin 24 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 dpavlin 2 console_init();
799     cpu_init();
800     device_init();
801     machine_init();
802 dpavlin 32 timer_init();
803 dpavlin 2 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 dpavlin 34 emuls[0] = emul_new(NULL, 0);
814 dpavlin 2 if (emuls[0] == NULL) {
815     fprintf(stderr, "out of memory\n");
816     exit(1);
817     }
818 dpavlin 32 settings_add(global_settings, "emul[0]", 1,
819     SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
820 dpavlin 2
821 dpavlin 4 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
822 dpavlin 2
823 dpavlin 32 if (!skip_srandom_call) {
824     struct timeval tv;
825     gettimeofday(&tv, NULL);
826     srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
827 dpavlin 2 }
828    
829     /* Print startup message: */
830     debug("GXemul");
831     #ifdef VERSION
832 dpavlin 28 debug(" " VERSION);
833 dpavlin 2 #endif
834 dpavlin 34 debug(" Copyright (C) 2003-2007 Anders Gavare\n");
835 dpavlin 2 debug("Read the source code and/or documentation for "
836     "other Copyright messages.\n\n");
837    
838 dpavlin 32 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
839 dpavlin 2 n_emuls --;
840 dpavlin 32 } else {
841 dpavlin 4 for (i=0; i<n_diskimages; i++)
842     diskimage_add(emuls[0]->machines[0], diskimages[i]);
843     }
844 dpavlin 2
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 dpavlin 32 char tmpstr[50];
866 dpavlin 2 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 dpavlin 22
883 dpavlin 32 /* 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 dpavlin 22 emuls[n_emuls - 1] =
891 dpavlin 34 emul_create_from_configfile(s, n_emuls - 1);
892 dpavlin 32
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 dpavlin 2 }
898     }
899    
900     if (n_emuls == 0) {
901 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
902 dpavlin 12 "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 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
905     "image.\n", progname);
906 dpavlin 2 exit(1);
907     }
908    
909     device_set_exit_on_error(0);
910 dpavlin 22 console_warn_if_slaves_are_needed(1);
911 dpavlin 2
912 dpavlin 32
913 dpavlin 2 /* Run all emulations: */
914     emul_run(emuls, n_emuls);
915    
916 dpavlin 32
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 dpavlin 24 settings_destroy(global_settings);
928    
929 dpavlin 34 #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 dpavlin 2 return 0;
942     }
943    

  ViewVC Help
Powered by ViewVC 1.1.26