/[gxemul]/trunk/src/main.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show 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 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: main.c,v 1.293 2007/02/05 16:49:05 debug Exp $
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37
38 #include "console.h"
39 #include "cpu.h"
40 #include "debugger.h"
41 #include "device.h"
42 #include "diskimage.h"
43 #include "emul.h"
44 #include "machine.h"
45 #include "misc.h"
46 #include "settings.h"
47 #include "timer.h"
48
49
50 extern volatile int single_step;
51 extern int force_debugger_at_exit;
52
53 extern int optind;
54 extern char *optarg;
55
56 struct settings *global_settings;
57
58 int extra_argc;
59 char **extra_argv;
60 char *progname;
61
62 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
63 int native_code_translation_enabled = 0;
64 int skip_srandom_call = 0;
65
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 printf(" " VERSION);
202 #endif
203 printf(" Copyright (C) 2003-2007 Anders Gavare\n");
204 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 printf(" or %s [general options] @configfile\n", progname);
210 #ifdef UNSTABLE_DEVEL
211 printf(" or %s [userland, other, and general options] file "
212 "[args ...]\n", progname);
213 #endif
214
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 printf(" b specifies that this is the boot"
234 " device\n");
235 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 printf(" oOFS; set base offset to OFS (for ISO9660"
242 " filesystems)\n");
243 printf(" r read-only (don't allow changes to the"
244 " file)\n");
245 printf(" s SCSI\n");
246 printf(" t tape\n");
247 printf(" 0-7 force a specific ID\n");
248 printf(" -G port listen to gdb remote connections on this port\n");
249 printf(" -I hz set the main cpu frequency to hz (not used by "
250 "all combinations\n of machines and guest OSes)\n");
251 printf(" -i display each instruction as it is executed\n");
252 printf(" -J disable dyntrans instruction combinations\n");
253 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 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 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 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 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 printf(" -T halt on non-existant memory accesses\n");
292 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 "(default is on when\n using configuration files or"
298 " when X11 is used, off otherwise)\n");
299 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 #ifdef UNSTABLE_DEVEL
308 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 #endif
312
313 printf("\nGeneral options:\n");
314 #ifdef UNSTABLE_DEVEL
315 printf(" -b enable native code generation\n");
316 printf(" -B disable native code generation\n");
317 #endif
318 printf(" -c cmd add cmd as a command to run before starting "
319 "the simulation\n");
320 printf(" -D skip the srandom call at startup\n");
321 printf(" -H display a list of possible CPU and "
322 "machine types\n");
323 printf(" -h display this help message\n");
324 printf(" -k n set dyntrans translation caches to n MB (default"
325 " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
326 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 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
341 "Examples:\n"
342 " 0xbfc00000:rom.bin for a raw ROM image\n"
343 " 0xbfc00000:0x100:rom.bin for an image with "
344 "0x100 bytes header\n"
345 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
346 "start with pc=0xbfc00884\n");
347 }
348
349
350 /*
351 * get_cmd_args():
352 *
353 * Reads command line arguments.
354 */
355 int get_cmd_args(int argc, char *argv[], struct emul *emul,
356 char ***diskimagesp, int *n_diskimagesp)
357 {
358 int ch, res, using_switch_d = 0, using_switch_Z = 0;
359 int using_switch_e = 0, using_switch_E = 0;
360 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 char *opts =
366 #ifdef UNSTABLE_DEVEL
367 "bB"
368 #endif
369 "C:c:Dd:E:e:G:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtU"
370 #ifdef UNSTABLE_DEVEL
371 "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 switch (ch) {
381 #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 case 'C':
395 m->cpu_name = strdup(optarg);
396 msopts = 1;
397 break;
398 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 case 'D':
410 skip_srandom_call = 1;
411 break;
412 case 'd':
413 /* 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 using_switch_d = 1;
423 msopts = 1;
424 break;
425 case 'E':
426 if (using_switch_E ++ > 0) {
427 fprintf(stderr, "-E already used.\n");
428 exit(1);
429 }
430 type = optarg;
431 msopts = 1;
432 break;
433 case 'e':
434 if (using_switch_e ++ > 0) {
435 fprintf(stderr, "-e already used.\n");
436 exit(1);
437 }
438 subtype = optarg;
439 msopts = 1;
440 break;
441 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 /* Note: implicit -V */
449 single_step = ENTER_SINGLE_STEPPING;
450 msopts = 1;
451 break;
452 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 m->allow_instruction_combinations = 0;
468 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 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 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 case 's':
548 machine_statistics_init(m, optarg);
549 native_code_translation_enabled = 0;
550 msopts = 1;
551 break;
552 case 'T':
553 m->halt_on_nonexistant_memaccess = 1;
554 msopts = 1;
555 break;
556 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 single_step = ENTER_SINGLE_STEPPING;
575 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 /* FALL-THROUGH */
586 case 'x':
587 console_allow_slaves(1);
588 break;
589 case 'Y':
590 m->x11_scaledown = atoi(optarg);
591 if (m->x11_scaledown < -1) {
592 m->x11_scaleup = - m->x11_scaledown;
593 m->x11_scaledown = 1;
594 }
595 if (m->x11_scaledown < 1) {
596 fprintf(stderr, "Invalid scaledown value.\n");
597 exit(1);
598 }
599 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 fprintf(stderr, "Run %s -h for help on command "
626 "line options.\n", progname);
627 exit(1);
628 }
629 }
630
631 if (type != NULL || subtype != NULL) {
632 if (type == NULL)
633 type = "";
634 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 /* -i and -r are pretty verbose: */
657
658 if (m->instruction_trace && !verbose) {
659 fprintf(stderr, "Implicitly %sturning on -v, because"
660 " of -i\n", quiet_mode? "turning off -q and " : "");
661 verbose = 1;
662 quiet_mode = 0;
663 }
664
665 if (m->register_dump && !verbose) {
666 fprintf(stderr, "Implicitly %sturning on -v, because"
667 " of -r\n", quiet_mode? "turning off -q and " : "");
668 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 * file. If no kernel is supplied, but a diskimage is being used,
678 * then try to boot from disk.
679 */
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 /* 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 struct emul **emuls;
744 char **diskimages = NULL;
745 int n_diskimages = 0;
746 int n_emuls;
747 int i;
748
749
750 #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 progname = argv[0];
762
763
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 global_settings = settings_new();
771
772 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 /* 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 settings_add(global_settings, "single_step", 0,
786 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
787
788 /* Read/write settings: */
789 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 console_init();
799 cpu_init();
800 device_init();
801 machine_init();
802 timer_init();
803 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 emuls[0] = emul_new(NULL, 0);
814 if (emuls[0] == NULL) {
815 fprintf(stderr, "out of memory\n");
816 exit(1);
817 }
818 settings_add(global_settings, "emul[0]", 1,
819 SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
820
821 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
822
823 if (!skip_srandom_call) {
824 struct timeval tv;
825 gettimeofday(&tv, NULL);
826 srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
827 }
828
829 /* Print startup message: */
830 debug("GXemul");
831 #ifdef VERSION
832 debug(" " VERSION);
833 #endif
834 debug(" Copyright (C) 2003-2007 Anders Gavare\n");
835 debug("Read the source code and/or documentation for "
836 "other Copyright messages.\n\n");
837
838 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
839 n_emuls --;
840 } else {
841 for (i=0; i<n_diskimages; i++)
842 diskimage_add(emuls[0]->machines[0], diskimages[i]);
843 }
844
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 char tmpstr[50];
866 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
883 /* 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 emuls[n_emuls - 1] =
891 emul_create_from_configfile(s, n_emuls - 1);
892
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 }
898 }
899
900 if (n_emuls == 0) {
901 fprintf(stderr, "No emulations defined. Maybe you forgot to "
902 "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 "to boot an emulated DECstation 5000/200 with a disk "
905 "image.\n", progname);
906 exit(1);
907 }
908
909 device_set_exit_on_error(0);
910 console_warn_if_slaves_are_needed(1);
911
912
913 /* Run all emulations: */
914 emul_run(emuls, n_emuls);
915
916
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 settings_destroy(global_settings);
928
929 #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 return 0;
942 }
943

  ViewVC Help
Powered by ViewVC 1.1.26