/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25389 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

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