/[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 12 - (hide annotations)
Mon Oct 8 16:18:38 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 21378 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 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 dpavlin 12 * $Id: main.c,v 1.243 2005/08/07 17:42:02 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     #include "device.h"
41     #include "diskimage.h"
42     #include "emul.h"
43     #include "machine.h"
44     #include "misc.h"
45    
46    
47     extern volatile int single_step;
48     extern int force_debugger_at_exit;
49     extern int show_opcode_statistics;
50    
51     extern int optind;
52     extern char *optarg;
53    
54     int extra_argc;
55     char **extra_argv;
56     char *progname;
57    
58     int fully_deterministic = 0;
59    
60    
61     /*****************************************************************************
62     *
63     * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
64     * The global variable quiet_mode can be used to suppress the output
65     * of debug(), but not the output of fatal().
66     *
67     *****************************************************************************/
68    
69     int verbose = 0;
70     int quiet_mode = 0;
71    
72     static int debug_indent = 0;
73     static int debug_currently_at_start_of_line = 1;
74    
75    
76     /*
77     * va_debug():
78     *
79     * Used internally by debug() and fatal().
80     */
81     static void va_debug(va_list argp, char *fmt)
82     {
83     char buf[DEBUG_BUFSIZE + 1];
84     char *s;
85     int i;
86    
87     buf[0] = buf[DEBUG_BUFSIZE] = 0;
88     vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
89    
90     s = buf;
91     while (*s) {
92     if (debug_currently_at_start_of_line) {
93     for (i=0; i<debug_indent; i++)
94     printf(" ");
95     }
96    
97     printf("%c", *s);
98    
99     debug_currently_at_start_of_line = 0;
100     if (*s == '\n' || *s == '\r')
101     debug_currently_at_start_of_line = 1;
102     s++;
103     }
104     }
105    
106    
107     /*
108     * debug_indentation():
109     *
110     * Modify the debug indentation.
111     */
112     void debug_indentation(int diff)
113     {
114     debug_indent += diff;
115     if (debug_indent < 0)
116     fprintf(stderr, "WARNING: debug_indent less than 0!\n");
117     }
118    
119    
120     /*
121     * debug():
122     *
123     * Debug output (ignored if quiet_mode is set).
124     */
125     void debug(char *fmt, ...)
126     {
127     va_list argp;
128    
129     if (quiet_mode)
130     return;
131    
132     va_start(argp, fmt);
133     va_debug(argp, fmt);
134     va_end(argp);
135     }
136    
137    
138     /*
139     * fatal():
140     *
141     * Fatal works like debug(), but doesn't care about the quiet_mode
142     * setting.
143     */
144     void fatal(char *fmt, ...)
145     {
146     va_list argp;
147    
148     va_start(argp, fmt);
149     va_debug(argp, fmt);
150     va_end(argp);
151     }
152    
153    
154     /*****************************************************************************/
155    
156    
157     /*
158     * internal_w():
159     *
160     * For internal use by gxemul itself.
161     */
162     void internal_w(char *arg)
163     {
164     if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
165     fprintf(stderr, "-W is for internal use by gxemul,"
166     " not for manual use.\n");
167     exit(1);
168     }
169    
170     arg += 2;
171    
172     switch (arg[0]) {
173     case 'S':
174     console_slave(arg + 1);
175     break;
176     default:
177     fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
178     arg);
179     }
180     }
181    
182    
183     /*****************************************************************************/
184    
185    
186     /*
187     * usage():
188     *
189     * Prints program usage to stdout.
190     */
191     static void usage(int longusage)
192     {
193     printf("GXemul");
194     #ifdef VERSION
195     printf("-" VERSION);
196     #endif
197     printf(" Copyright (C) 2003-2005 Anders Gavare\n");
198     printf("Read the source code and/or documentation for "
199     "other Copyright messages.\n");
200    
201     printf("\nusage: %s [machine, other, and general options] [file "
202     "[...]]\n", progname);
203     printf(" or %s [general options] @configfile [...]\n", progname);
204     printf(" or %s [userland, other, and general options] file "
205     "[args ...]\n", progname);
206    
207     if (!longusage) {
208     printf("\nRun %s -h for help on command line options.\n",
209     progname);
210     return;
211     }
212    
213     printf("\nMachine selection options:\n");
214     printf(" -E t try to emulate machine type t. (Use -H to get "
215     "a list of types.)\n");
216     printf(" -e st try to emulate machine subtype st. (Use this "
217     "with -E.)\n");
218    
219     printf("\nOther options:\n");
220 dpavlin 12 printf(" -A disable alignment checks in some cases (for higher"
221     " speed)\n");
222 dpavlin 2 #ifdef BINTRANS
223 dpavlin 10 printf(" -B disable dynamic binary translation. (translation"
224     " is turned on\n by default, if the host "
225     "supports it)\n");
226 dpavlin 2 #endif
227     printf(" -C x try to emulate a specific CPU. (Use -H to get a "
228     "list of types.)\n");
229     printf(" -d fname add fname as a disk image. You can add \"xxx:\""
230     " as a prefix\n");
231     printf(" where xxx is one or more of the following:\n");
232 dpavlin 6 printf(" b specifies that this is the boot"
233 dpavlin 2 " device\n");
234 dpavlin 6 printf(" c CD-ROM\n");
235     printf(" d DISK\n");
236     printf(" f FLOPPY\n");
237     printf(" gH;S; set geometry to H heads and S"
238     " sectors-per-track\n");
239     printf(" i IDE\n");
240     printf(" r read-only (don't allow changes to the"
241 dpavlin 2 " file)\n");
242 dpavlin 6 printf(" s SCSI\n");
243     printf(" t tape\n");
244     printf(" 0-7 force a specific ID\n");
245 dpavlin 2 printf(" -I x emulate clock interrupts at x Hz (affects"
246     " rtc devices only, not\n");
247     printf(" actual runtime speed) (this disables automatic"
248     " clock adjustments)\n");
249     printf(" -i display each instruction as it is executed\n");
250     printf(" -J disable some speed tricks\n");
251     printf(" -j name set the name of the kernel, for example:\n");
252     printf(" -j netbsd for NetBSD/pmax\n");
253     printf(" -j bsd for OpenBSD/pmax\n");
254     printf(" -j vmunix for Ultrix/RISC\n");
255     printf(" -M m emulate m MBs of physical RAM\n");
256     printf(" -m nr run at most nr instructions (on any cpu)\n");
257     printf(" -N display nr of instructions/second average, at"
258     " regular intervals\n");
259     printf(" -n nr set nr of CPUs (for SMP experiments)\n");
260     printf(" -O force netboot (tftp instead of disk), even when"
261     " a disk image is\n"
262     " present (for DECstation, SGI, and ARC emulation)\n");
263     printf(" -o arg set the boot argument (for DEC, ARC, or SGI"
264     " emulation).\n");
265     printf(" Default arg for DEC is '-a', for ARC '-aN'.\n");
266     printf(" -p pc add a breakpoint (remember to use the '0x' "
267     "prefix for hex!)\n");
268     printf(" -Q no built-in PROM emulation (use this for "
269     "running ROM images)\n");
270     printf(" -R use random bootstrap cpu, instead of nr 0\n");
271     printf(" -r register dumps before every instruction\n");
272     printf(" -S initialize emulated RAM to random bytes, "
273     "instead of zeroes\n");
274     printf(" -T enter the single-step debugger on "
275     "unimplemented memory accesses\n");
276     printf(" -t show function trace tree\n");
277     printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
278     #ifdef WITH_X11
279     printf(" -X use X11\n");
280     #endif /* WITH_X11 */
281     printf(" -x open up new xterms for emulated serial ports "
282     "(default is on when\n using configuration files, off"
283     " otherwise)\n");
284     #ifdef WITH_X11
285     printf(" -Y n scale down framebuffer windows by n x n times\n");
286     #endif /* WITH_X11 */
287     printf(" -y x set max_random_cycles_per_chunk to x"
288     " (experimental)\n");
289     printf(" -Z n set nr of graphics cards, for emulating a "
290     "dual-head or tripple-head\n"
291     " environment (only for DECstation emulation)\n");
292     printf(" -z disp add disp as an X11 display to use for "
293     "framebuffers\n");
294    
295     printf("\nUserland options:\n");
296     printf(" -u emul userland-only (syscall) emulation (use -H to"
297     " get a list of\n available emulation modes)\n");
298    
299     printf("\nGeneral options:\n");
300     printf(" -D guarantee fully deterministic behaviour\n");
301     printf(" -H display a list of possible CPU and "
302     "machine types\n");
303     printf(" -h display this help message\n");
304     printf(" -K force the debugger to be entered at the end "
305     "of a simulation\n");
306     printf(" -q quiet mode (don't print startup messages)\n");
307     printf(" -s show opcode usage statistics after simulation\n");
308     printf(" -V start up in the single-step debugger, paused\n");
309     printf(" -v verbose debug messages\n");
310     printf("\n");
311     printf("If you are selecting a machine type to emulate directly "
312     "on the command line,\nthen you must specify one or more names"
313     " of files that you wish to load into\n"
314     "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
315     "where syms is the text produced by running 'nm' (or 'nm -S') "
316     "on a binary.\n"
317     "To load a raw binary into memory, add \"address:\" in front "
318     "of the filename,\n"
319 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
320 dpavlin 2 "Examples:\n"
321 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
322     " 0xbfc00000:0x100:rom.bin for an image with "
323 dpavlin 2 "0x100 bytes header\n"
324 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
325 dpavlin 2 "start with pc=0xbfc00884\n");
326     }
327    
328    
329     /*
330     * get_cmd_args():
331     *
332     * Reads command line arguments.
333     */
334 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
335     char ***diskimagesp, int *n_diskimagesp)
336 dpavlin 2 {
337     int ch, res, using_switch_d = 0, using_switch_Z = 0;
338     char *type = NULL, *subtype = NULL;
339     int n_cpus_set = 0;
340     int msopts = 0; /* Machine-specific options used */
341     struct machine *m = emul_add_machine(emul, "default");
342    
343 dpavlin 12 while ((ch = getopt(argc, argv, "ABC:Dd:E:e:HhI:iJj:KM:m:"
344 dpavlin 2 "Nn:Oo:p:QqRrSsTtUu:VvW:XxY:y:Z:z:")) != -1) {
345     switch (ch) {
346 dpavlin 12 case 'A':
347     m->dyntrans_alignment_check = 0;
348     msopts = 1;
349     break;
350 dpavlin 2 case 'B':
351     m->bintrans_enable = 0;
352     msopts = 1;
353     break;
354     case 'C':
355     m->cpu_name = strdup(optarg);
356     msopts = 1;
357     break;
358     case 'D':
359     fully_deterministic = 1;
360     break;
361     case 'd':
362 dpavlin 4 /* diskimage_add() is called further down */
363     (*n_diskimagesp) ++;
364     (*diskimagesp) = realloc(*diskimagesp,
365     sizeof(char *) * (*n_diskimagesp));
366     if (*diskimagesp == NULL) {
367     fprintf(stderr, "out of memory\n");
368     exit(1);
369     }
370     (*diskimagesp)[(*n_diskimagesp) - 1] = strdup(optarg);
371 dpavlin 2 using_switch_d = 1;
372     msopts = 1;
373     break;
374     case 'E':
375     type = optarg;
376     msopts = 1;
377     break;
378     case 'e':
379     subtype = optarg;
380     msopts = 1;
381     break;
382     case 'H':
383     machine_list_available_types_and_cpus();
384     exit(1);
385     case 'h':
386     usage(1);
387     exit(1);
388     case 'I':
389     m->emulated_hz = atoi(optarg);
390     m->automatic_clock_adjustment = 0;
391     msopts = 1;
392     break;
393     case 'i':
394     m->instruction_trace = 1;
395     msopts = 1;
396     break;
397     case 'J':
398     m->speed_tricks = 0;
399     msopts = 1;
400     break;
401     case 'j':
402     m->boot_kernel_filename = strdup(optarg);
403     if (m->boot_kernel_filename == NULL) {
404     fprintf(stderr, "out of memory\n");
405     exit(1);
406     }
407     msopts = 1;
408     break;
409     case 'K':
410     force_debugger_at_exit = 1;
411     break;
412     case 'M':
413     m->physical_ram_in_mb = atoi(optarg);
414     msopts = 1;
415     break;
416     case 'm':
417     m->max_instructions = atoi(optarg);
418     msopts = 1;
419     break;
420     case 'N':
421     m->show_nr_of_instructions = 1;
422     msopts = 1;
423     break;
424     case 'n':
425     m->ncpus = atoi(optarg);
426     n_cpus_set = 1;
427     msopts = 1;
428     break;
429     case 'O':
430     m->force_netboot = 1;
431     msopts = 1;
432     break;
433     case 'o':
434     m->boot_string_argument = strdup(optarg);
435     if (m->boot_string_argument == NULL) {
436     fprintf(stderr, "out of memory\n");
437     exit(1);
438     }
439     msopts = 1;
440     break;
441     case 'p':
442     if (m->n_breakpoints >= MAX_BREAKPOINTS) {
443     fprintf(stderr, "too many breakpoints\n");
444     exit(1);
445     }
446     m->breakpoint_string[m->n_breakpoints] = strdup(optarg);
447     if (m->breakpoint_string[m->n_breakpoints] == NULL) {
448     fprintf(stderr, "out of memory\n");
449     exit(1);
450     }
451     m->breakpoint_flags[m->n_breakpoints] = 0;
452     m->n_breakpoints ++;
453     msopts = 1;
454     break;
455     case 'Q':
456     m->prom_emulation = 0;
457     msopts = 1;
458     break;
459     case 'q':
460     quiet_mode = 1;
461     break;
462     case 'R':
463     m->use_random_bootstrap_cpu = 1;
464     msopts = 1;
465     break;
466     case 'r':
467     m->register_dump = 1;
468     msopts = 1;
469     break;
470     case 'S':
471     m->random_mem_contents = 1;
472     msopts = 1;
473     break;
474     case 's':
475     show_opcode_statistics = 1;
476     break;
477     case 'T':
478     m->single_step_on_bad_addr = 1;
479     msopts = 1;
480     break;
481     case 't':
482     m->show_trace_tree = 1;
483     msopts = 1;
484     break;
485     case 'U':
486     m->slow_serial_interrupts_hack_for_linux = 1;
487     msopts = 1;
488     break;
489     case 'u':
490     m->userland_emul = strdup(optarg);
491     if (m->userland_emul == NULL) {
492     fprintf(stderr, "out of memory\n");
493     exit(1);
494     }
495     m->machine_type = MACHINE_USERLAND;
496     msopts = 1;
497     break;
498     case 'V':
499     single_step = 1;
500     break;
501     case 'v':
502     verbose ++;
503     break;
504     case 'W':
505     internal_w(optarg);
506     exit(0);
507     case 'X':
508     m->use_x11 = 1;
509     msopts = 1;
510     break;
511     case 'x':
512     console_allow_slaves(1);
513     break;
514     case 'Y':
515     m->x11_scaledown = atoi(optarg);
516 dpavlin 4 if (m->x11_scaledown < 1) {
517     fprintf(stderr, "Invalid scaledown value.\n");
518     exit(1);
519     }
520 dpavlin 2 msopts = 1;
521     break;
522     case 'y':
523     m->max_random_cycles_per_chunk = atoi(optarg);
524     msopts = 1;
525     break;
526     case 'Z':
527     m->n_gfx_cards = atoi(optarg);
528     using_switch_Z = 1;
529     msopts = 1;
530     break;
531     case 'z':
532     m->x11_n_display_names ++;
533     m->x11_display_names = realloc(
534     m->x11_display_names,
535     m->x11_n_display_names * sizeof(char *));
536     if (m->x11_display_names == NULL) {
537     fprintf(stderr, "out of memory\n");
538     exit(1);
539     }
540     m->x11_display_names[m->x11_n_display_names-1] =
541     strdup(optarg);
542     if (m->x11_display_names
543     [m->x11_n_display_names-1] == NULL) {
544     fprintf(stderr, "out of memory\n");
545     exit(1);
546     }
547     msopts = 1;
548     break;
549     default:
550 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
551     "line options.\n", progname);
552 dpavlin 2 exit(1);
553     }
554     }
555    
556 dpavlin 12 if (type != NULL || subtype != NULL) {
557     if (type == NULL)
558     type = "";
559 dpavlin 2 if (subtype == NULL)
560     subtype = "";
561     res = machine_name_to_type(type, subtype,
562     &m->machine_type, &m->machine_subtype, &m->arch);
563     if (!res)
564     exit(1);
565     }
566    
567     argc -= optind;
568     argv += optind;
569    
570     extra_argc = argc;
571     extra_argv = argv;
572    
573    
574     if (m->machine_type == MACHINE_NONE && msopts) {
575     fprintf(stderr, "Machine specific options used directly on "
576     "the command line, but no machine\nemulation specified?\n");
577     exit(1);
578     }
579    
580    
581 dpavlin 12 /* -i and -r are pretty verbose: */
582 dpavlin 2
583     if (m->instruction_trace && !verbose) {
584 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
585     " of -i\n", quiet_mode? "turning off -q and " : "");
586 dpavlin 2 verbose = 1;
587     quiet_mode = 0;
588     }
589    
590     if (m->register_dump && !verbose) {
591 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
592     " of -r\n", quiet_mode? "turning off -q and " : "");
593 dpavlin 2 verbose = 1;
594     quiet_mode = 0;
595     }
596    
597 dpavlin 10 if ((m->instruction_trace || m->register_dump || m->show_trace_tree)
598     && m->bintrans_enable) {
599     fprintf(stderr, "Implicitly turning off bintrans.\n");
600     m->bintrans_enable = 0;
601     }
602 dpavlin 2
603 dpavlin 10
604 dpavlin 2 /*
605     * Usually, an executable filename must be supplied.
606     *
607     * However, it is possible to boot directly from a harddisk image
608 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
609     * then try to boot from disk.
610 dpavlin 2 */
611     if (extra_argc == 0) {
612     if (using_switch_d) {
613     /* Booting directly from a disk image... */
614     } else {
615     usage(0);
616     fprintf(stderr, "\nNo filename given. Aborting.\n");
617     exit(1);
618     }
619     } else if (m->boot_kernel_filename[0] == '\0') {
620     /*
621     * Default boot_kernel_filename is "", which can be overriden
622     * by the -j command line option. If it is still "" here,
623     * and we're not booting directly from a disk image, then
624     * try to set it to the last part of the last file name
625     * given on the command line. (Last part = the stuff after
626     * the last slash.)
627     */
628     char *s = extra_argv[extra_argc - 1];
629     char *s2;
630    
631     s2 = strrchr(s, '/');
632     if (s2 == NULL)
633     s2 = s;
634     else
635     s2 ++;
636    
637     m->boot_kernel_filename = strdup(s2);
638     if (m->boot_kernel_filename == NULL) {
639     fprintf(stderr, "out of memory\n");
640     exit(1);
641     }
642     }
643    
644     if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
645     fprintf(stderr, "Bad number of gfx cards (-Z).\n");
646     exit(1);
647     }
648    
649     if (m->bintrans_enable) {
650     m->speed_tricks = 0;
651     /* TODO: Print a warning about this? */
652     }
653    
654 dpavlin 12 if (m->n_breakpoints > 0 &&
655     m->bintrans_enable && m->arch == ARCH_MIPS) {
656     fprintf(stderr, "Breakpoints and MIPS binary translation "
657 dpavlin 2 "don't work too well together right now.\n");
658     exit(1);
659     }
660    
661     #ifndef BINTRANS
662     if (m->bintrans_enable) {
663     fprintf(stderr, "WARNING: %s was compiled without "
664     "bintrans support. Ignoring -b.\n", progname);
665     m->bintrans_enable = 0;
666     }
667     #endif
668    
669     #ifndef WITH_X11
670     if (m->use_x11) {
671     fprintf(stderr, "WARNING: %s was compiled without "
672     "X11 support. Ignoring -X.\n", progname);
673     m->use_x11 = 0;
674     }
675     #endif
676    
677     if (!using_switch_Z && !m->use_x11)
678     m->n_gfx_cards = 0;
679    
680     m->bintrans_enabled_from_start = m->bintrans_enable;
681    
682     return 0;
683     }
684    
685    
686     /*
687     * main():
688     *
689     * Two kinds of emulations are started from here:
690     *
691     * o) Simple emulations, using command line arguments, compatible with
692     * earlier version of GXemul/mips64emul.
693     *
694     * o) Emulations set up by parsing special config files. (0 or more.)
695     */
696     int main(int argc, char *argv[])
697     {
698     struct emul **emuls;
699 dpavlin 4 char **diskimages = NULL;
700     int n_diskimages = 0;
701 dpavlin 2 int n_emuls;
702     int i;
703    
704     progname = argv[0];
705    
706     console_init();
707     cpu_init();
708     device_init();
709     machine_init();
710     useremul_init();
711    
712     emuls = malloc(sizeof(struct emul *));
713     if (emuls == NULL) {
714     fprintf(stderr, "out of memory\n");
715     exit(1);
716     }
717    
718     /* Allocate space for a simple emul setup: */
719     n_emuls = 1;
720     emuls[0] = emul_new(NULL);
721     if (emuls[0] == NULL) {
722     fprintf(stderr, "out of memory\n");
723     exit(1);
724     }
725    
726 dpavlin 4 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
727 dpavlin 2
728     if (!fully_deterministic) {
729     /* TODO: More than just time(). Use gettimeofday(). */
730     srandom(time(NULL) ^ (getpid() << 12));
731     } else {
732     /* Fully deterministic. -I must have been supplied. */
733     if (emuls[0]->machines[0]->automatic_clock_adjustment) {
734     fatal("Cannot have -D without -I.\n");
735     exit(1);
736     }
737     }
738    
739     /* Print startup message: */
740     debug("GXemul");
741     #ifdef VERSION
742     debug("-" VERSION);
743     #endif
744     debug(" Copyright (C) 2003-2005 Anders Gavare\n");
745     debug("Read the source code and/or documentation for "
746     "other Copyright messages.\n\n");
747    
748     if (emuls[0]->machines[0]->machine_type == MACHINE_NONE)
749     n_emuls --;
750 dpavlin 4 else {
751     for (i=0; i<n_diskimages; i++)
752     diskimage_add(emuls[0]->machines[0], diskimages[i]);
753     }
754 dpavlin 2
755     /* Simple initialization, from command line arguments: */
756     if (n_emuls > 0) {
757     /* Make sure that there are no configuration files as well: */
758     for (i=1; i<argc; i++)
759     if (argv[i][0] == '@') {
760     fprintf(stderr, "You can either start one "
761     "emulation with one machine directly from "
762     "the command\nline, or start one or more "
763     "emulations using configuration files."
764     " Not both.\n");
765     exit(1);
766     }
767    
768     /* Initialize one emul: */
769     emul_simple_init(emuls[0]);
770     }
771    
772     /* Initialize emulations from config files: */
773     for (i=1; i<argc; i++) {
774     if (argv[i][0] == '@') {
775     char *s = argv[i] + 1;
776     if (strlen(s) == 0 && i+1 < argc &&
777     argv[i+1][0] != '@') {
778     i++;
779     s = argv[i];
780     }
781     n_emuls ++;
782     emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
783     if (emuls == NULL) {
784     fprintf(stderr, "out of memory\n");
785     exit(1);
786     }
787     emuls[n_emuls - 1] =
788     emul_create_from_configfile(s);
789    
790     /* Always allow slave xterms when using multiple
791     emulations: */
792     console_allow_slaves(1);
793     }
794     }
795    
796     if (n_emuls == 0) {
797 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
798 dpavlin 12 "use -E xx and/or -e yy, to specify\nthe machine type."
799     " For example:\n\n %s -e 3max -d disk.img\n\n"
800 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
801     "image.\n", progname);
802 dpavlin 2 exit(1);
803     }
804    
805     device_set_exit_on_error(0);
806    
807     /* Run all emulations: */
808     emul_run(emuls, n_emuls);
809    
810     return 0;
811     }
812    

  ViewVC Help
Powered by ViewVC 1.1.26