/[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 38 - (hide 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 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 38 * $Id: main.c,v 1.296 2007/03/31 15:11:26 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 dpavlin 38 #ifdef TEST_NATIVE_X86
50     #include "native_x86.h"
51     #endif
52 dpavlin 2
53 dpavlin 38
54 dpavlin 2 extern volatile int single_step;
55     extern int force_debugger_at_exit;
56    
57     extern int optind;
58     extern char *optarg;
59    
60 dpavlin 24 struct settings *global_settings;
61    
62 dpavlin 2 int extra_argc;
63     char **extra_argv;
64     char *progname;
65    
66 dpavlin 34 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
67     int native_code_translation_enabled = 0;
68 dpavlin 32 int skip_srandom_call = 0;
69 dpavlin 2
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 dpavlin 28 printf(" " VERSION);
206 dpavlin 2 #endif
207 dpavlin 34 printf(" Copyright (C) 2003-2007 Anders Gavare\n");
208 dpavlin 2 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 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
214 dpavlin 24 #ifdef UNSTABLE_DEVEL
215 dpavlin 2 printf(" or %s [userland, other, and general options] file "
216     "[args ...]\n", progname);
217 dpavlin 24 #endif
218 dpavlin 2
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 dpavlin 6 printf(" b specifies that this is the boot"
238 dpavlin 2 " device\n");
239 dpavlin 6 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 dpavlin 34 printf(" oOFS; set base offset to OFS (for ISO9660"
246     " filesystems)\n");
247 dpavlin 6 printf(" r read-only (don't allow changes to the"
248 dpavlin 2 " file)\n");
249 dpavlin 6 printf(" s SCSI\n");
250     printf(" t tape\n");
251 dpavlin 38 printf(" V add an overlay\n");
252 dpavlin 6 printf(" 0-7 force a specific ID\n");
253 dpavlin 32 printf(" -I hz set the main cpu frequency to hz (not used by "
254 dpavlin 34 "all combinations\n of machines and guest OSes)\n");
255 dpavlin 2 printf(" -i display each instruction as it is executed\n");
256 dpavlin 28 printf(" -J disable dyntrans instruction combinations\n");
257 dpavlin 24 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 dpavlin 2 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 dpavlin 24 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 dpavlin 2 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 dpavlin 28 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 dpavlin 34 printf(" -T halt on non-existant memory accesses\n");
296 dpavlin 2 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 dpavlin 22 "(default is on when\n using configuration files or"
302     " when X11 is used, off otherwise)\n");
303 dpavlin 2 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 dpavlin 24 #ifdef UNSTABLE_DEVEL
312 dpavlin 2 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 dpavlin 24 #endif
316 dpavlin 2
317     printf("\nGeneral options:\n");
318 dpavlin 34 #ifdef UNSTABLE_DEVEL
319     printf(" -b enable native code generation\n");
320     printf(" -B disable native code generation\n");
321     #endif
322 dpavlin 22 printf(" -c cmd add cmd as a command to run before starting "
323     "the simulation\n");
324 dpavlin 32 printf(" -D skip the srandom call at startup\n");
325 dpavlin 2 printf(" -H display a list of possible CPU and "
326     "machine types\n");
327     printf(" -h display this help message\n");
328 dpavlin 34 printf(" -k n set dyntrans translation caches to n MB (default"
329     " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
330 dpavlin 2 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 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
345 dpavlin 2 "Examples:\n"
346 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
347     " 0xbfc00000:0x100:rom.bin for an image with "
348 dpavlin 2 "0x100 bytes header\n"
349 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
350 dpavlin 2 "start with pc=0xbfc00884\n");
351     }
352    
353    
354     /*
355     * get_cmd_args():
356     *
357     * Reads command line arguments.
358     */
359 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
360     char ***diskimagesp, int *n_diskimagesp)
361 dpavlin 2 {
362     int ch, res, using_switch_d = 0, using_switch_Z = 0;
363 dpavlin 24 int using_switch_e = 0, using_switch_E = 0;
364 dpavlin 2 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 dpavlin 24 char *opts =
370     #ifdef UNSTABLE_DEVEL
371 dpavlin 34 "bB"
372     #endif
373 dpavlin 38 "C:c:Dd:E:e:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtU"
374 dpavlin 34 #ifdef UNSTABLE_DEVEL
375 dpavlin 24 "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 dpavlin 2 switch (ch) {
385 dpavlin 34 #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 dpavlin 2 case 'C':
399     m->cpu_name = strdup(optarg);
400     msopts = 1;
401     break;
402 dpavlin 22 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 dpavlin 2 case 'D':
414 dpavlin 32 skip_srandom_call = 1;
415 dpavlin 2 break;
416     case 'd':
417 dpavlin 4 /* 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 dpavlin 2 using_switch_d = 1;
427     msopts = 1;
428     break;
429     case 'E':
430 dpavlin 24 if (using_switch_E ++ > 0) {
431     fprintf(stderr, "-E already used.\n");
432     exit(1);
433     }
434 dpavlin 2 type = optarg;
435     msopts = 1;
436     break;
437     case 'e':
438 dpavlin 24 if (using_switch_e ++ > 0) {
439     fprintf(stderr, "-e already used.\n");
440     exit(1);
441     }
442 dpavlin 2 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 dpavlin 28 m->allow_instruction_combinations = 0;
461 dpavlin 2 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 dpavlin 34 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 dpavlin 2 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 dpavlin 28 case 's':
541     machine_statistics_init(m, optarg);
542 dpavlin 34 native_code_translation_enabled = 0;
543 dpavlin 28 msopts = 1;
544     break;
545 dpavlin 34 case 'T':
546     m->halt_on_nonexistant_memaccess = 1;
547     msopts = 1;
548     break;
549 dpavlin 2 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 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
568 dpavlin 2 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 dpavlin 22 /* FALL-THROUGH */
579 dpavlin 2 case 'x':
580     console_allow_slaves(1);
581     break;
582     case 'Y':
583     m->x11_scaledown = atoi(optarg);
584 dpavlin 20 if (m->x11_scaledown < -1) {
585     m->x11_scaleup = - m->x11_scaledown;
586     m->x11_scaledown = 1;
587     }
588 dpavlin 4 if (m->x11_scaledown < 1) {
589     fprintf(stderr, "Invalid scaledown value.\n");
590     exit(1);
591     }
592 dpavlin 2 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 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
619     "line options.\n", progname);
620 dpavlin 2 exit(1);
621     }
622     }
623    
624 dpavlin 12 if (type != NULL || subtype != NULL) {
625     if (type == NULL)
626     type = "";
627 dpavlin 2 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 dpavlin 12 /* -i and -r are pretty verbose: */
650 dpavlin 2
651     if (m->instruction_trace && !verbose) {
652 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
653     " of -i\n", quiet_mode? "turning off -q and " : "");
654 dpavlin 2 verbose = 1;
655     quiet_mode = 0;
656     }
657    
658     if (m->register_dump && !verbose) {
659 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
660     " of -r\n", quiet_mode? "turning off -q and " : "");
661 dpavlin 2 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 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
671     * then try to boot from disk.
672 dpavlin 2 */
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 dpavlin 32 /* 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 dpavlin 2 struct emul **emuls;
737 dpavlin 4 char **diskimages = NULL;
738     int n_diskimages = 0;
739 dpavlin 2 int n_emuls;
740     int i;
741    
742 dpavlin 32
743 dpavlin 38 /*
744     * Experimental profil() code, which works on my laptop.
745     * Don't use it for anything else.
746     */
747 dpavlin 34 #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 dpavlin 38 /* Experimental test code: */
759     #ifdef TEST_NATIVE_X86
760     test_native_x86();
761     #endif
762    
763    
764    
765 dpavlin 2 progname = argv[0];
766    
767 dpavlin 32
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 dpavlin 24 global_settings = settings_new();
775    
776 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 24 settings_add(global_settings, "single_step", 0,
790     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
791 dpavlin 34
792     /* Read/write settings: */
793 dpavlin 24 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 dpavlin 2 console_init();
803     cpu_init();
804     device_init();
805     machine_init();
806 dpavlin 32 timer_init();
807 dpavlin 2 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 dpavlin 34 emuls[0] = emul_new(NULL, 0);
818 dpavlin 2 if (emuls[0] == NULL) {
819     fprintf(stderr, "out of memory\n");
820     exit(1);
821     }
822 dpavlin 32 settings_add(global_settings, "emul[0]", 1,
823     SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
824 dpavlin 2
825 dpavlin 4 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
826 dpavlin 2
827 dpavlin 32 if (!skip_srandom_call) {
828     struct timeval tv;
829     gettimeofday(&tv, NULL);
830     srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
831 dpavlin 2 }
832    
833     /* Print startup message: */
834     debug("GXemul");
835     #ifdef VERSION
836 dpavlin 28 debug(" " VERSION);
837 dpavlin 2 #endif
838 dpavlin 34 debug(" Copyright (C) 2003-2007 Anders Gavare\n");
839 dpavlin 2 debug("Read the source code and/or documentation for "
840     "other Copyright messages.\n\n");
841    
842 dpavlin 32 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
843 dpavlin 2 n_emuls --;
844 dpavlin 32 } else {
845 dpavlin 4 for (i=0; i<n_diskimages; i++)
846     diskimage_add(emuls[0]->machines[0], diskimages[i]);
847     }
848 dpavlin 2
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 dpavlin 32 char tmpstr[50];
870 dpavlin 2 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 dpavlin 22
887 dpavlin 32 /* 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 dpavlin 22 emuls[n_emuls - 1] =
895 dpavlin 34 emul_create_from_configfile(s, n_emuls - 1);
896 dpavlin 32
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 dpavlin 2 }
902     }
903    
904     if (n_emuls == 0) {
905 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
906 dpavlin 12 "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 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
909     "image.\n", progname);
910 dpavlin 2 exit(1);
911     }
912    
913     device_set_exit_on_error(0);
914 dpavlin 22 console_warn_if_slaves_are_needed(1);
915 dpavlin 2
916 dpavlin 32
917 dpavlin 2 /* Run all emulations: */
918     emul_run(emuls, n_emuls);
919    
920 dpavlin 32
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 dpavlin 24 settings_destroy(global_settings);
932    
933 dpavlin 34 #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 dpavlin 2 return 0;
946     }
947    

  ViewVC Help
Powered by ViewVC 1.1.26