/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 21372 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

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 14 * $Id: main.c,v 1.244 2005/09/07 07:41:29 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 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
204 dpavlin 2 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