/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 21567 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


1 /*
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 * $Id: main.c,v 1.248 2005/11/23 02:17:00 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 "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 printf(" -A disable alignment checks in some cases (for higher"
221 " speed)\n");
222 #ifdef BINTRANS
223 printf(" -B disable dynamic binary translation. (translation"
224 " is turned on\n by default, if the host "
225 "supports it)\n");
226 #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 printf(" b specifies that this is the boot"
233 " device\n");
234 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 " file)\n");
242 printf(" s SCSI\n");
243 printf(" t tape\n");
244 printf(" 0-7 force a specific ID\n");
245 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 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
320 "Examples:\n"
321 " 0xbfc00000:rom.bin for a raw ROM image\n"
322 " 0xbfc00000:0x100:rom.bin for an image with "
323 "0x100 bytes header\n"
324 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
325 "start with pc=0xbfc00884\n");
326 }
327
328
329 /*
330 * get_cmd_args():
331 *
332 * Reads command line arguments.
333 */
334 int get_cmd_args(int argc, char *argv[], struct emul *emul,
335 char ***diskimagesp, int *n_diskimagesp)
336 {
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 while ((ch = getopt(argc, argv, "ABC:Dd:E:e:HhI:iJj:KM:m:"
344 "Nn:Oo:p:QqRrSsTtUu:VvW:XxY:y:Z:z:")) != -1) {
345 switch (ch) {
346 case 'A':
347 m->dyntrans_alignment_check = 0;
348 msopts = 1;
349 break;
350 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 /* 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 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 if (m->x11_scaledown < -1) {
517 m->x11_scaleup = - m->x11_scaledown;
518 m->x11_scaledown = 1;
519 }
520 if (m->x11_scaledown < 1) {
521 fprintf(stderr, "Invalid scaledown value.\n");
522 exit(1);
523 }
524 msopts = 1;
525 break;
526 case 'y':
527 m->max_random_cycles_per_chunk = atoi(optarg);
528 msopts = 1;
529 break;
530 case 'Z':
531 m->n_gfx_cards = atoi(optarg);
532 using_switch_Z = 1;
533 msopts = 1;
534 break;
535 case 'z':
536 m->x11_n_display_names ++;
537 m->x11_display_names = realloc(
538 m->x11_display_names,
539 m->x11_n_display_names * sizeof(char *));
540 if (m->x11_display_names == NULL) {
541 fprintf(stderr, "out of memory\n");
542 exit(1);
543 }
544 m->x11_display_names[m->x11_n_display_names-1] =
545 strdup(optarg);
546 if (m->x11_display_names
547 [m->x11_n_display_names-1] == NULL) {
548 fprintf(stderr, "out of memory\n");
549 exit(1);
550 }
551 msopts = 1;
552 break;
553 default:
554 fprintf(stderr, "Run %s -h for help on command "
555 "line options.\n", progname);
556 exit(1);
557 }
558 }
559
560 if (type != NULL || subtype != NULL) {
561 if (type == NULL)
562 type = "";
563 if (subtype == NULL)
564 subtype = "";
565 res = machine_name_to_type(type, subtype,
566 &m->machine_type, &m->machine_subtype, &m->arch);
567 if (!res)
568 exit(1);
569 }
570
571 argc -= optind;
572 argv += optind;
573
574 extra_argc = argc;
575 extra_argv = argv;
576
577
578 if (m->machine_type == MACHINE_NONE && msopts) {
579 fprintf(stderr, "Machine specific options used directly on "
580 "the command line, but no machine\nemulation specified?\n");
581 exit(1);
582 }
583
584
585 /* -i and -r are pretty verbose: */
586
587 if (m->instruction_trace && !verbose) {
588 fprintf(stderr, "Implicitly %sturning on -v, because"
589 " of -i\n", quiet_mode? "turning off -q and " : "");
590 verbose = 1;
591 quiet_mode = 0;
592 }
593
594 if (m->register_dump && !verbose) {
595 fprintf(stderr, "Implicitly %sturning on -v, because"
596 " of -r\n", quiet_mode? "turning off -q and " : "");
597 verbose = 1;
598 quiet_mode = 0;
599 }
600
601 if ((m->instruction_trace || m->register_dump || m->show_trace_tree)
602 && m->bintrans_enable) {
603 if (m->arch == ARCH_MIPS)
604 fprintf(stderr, "Implicitly turning off bintrans.\n");
605 m->bintrans_enable = 0;
606 }
607
608
609 /*
610 * Usually, an executable filename must be supplied.
611 *
612 * However, it is possible to boot directly from a harddisk image
613 * file. If no kernel is supplied, but a diskimage is being used,
614 * then try to boot from disk.
615 */
616 if (extra_argc == 0) {
617 if (using_switch_d) {
618 /* Booting directly from a disk image... */
619 } else {
620 usage(0);
621 fprintf(stderr, "\nNo filename given. Aborting.\n");
622 exit(1);
623 }
624 } else if (m->boot_kernel_filename[0] == '\0') {
625 /*
626 * Default boot_kernel_filename is "", which can be overriden
627 * by the -j command line option. If it is still "" here,
628 * and we're not booting directly from a disk image, then
629 * try to set it to the last part of the last file name
630 * given on the command line. (Last part = the stuff after
631 * the last slash.)
632 */
633 char *s = extra_argv[extra_argc - 1];
634 char *s2;
635
636 s2 = strrchr(s, '/');
637 if (s2 == NULL)
638 s2 = s;
639 else
640 s2 ++;
641
642 m->boot_kernel_filename = strdup(s2);
643 if (m->boot_kernel_filename == NULL) {
644 fprintf(stderr, "out of memory\n");
645 exit(1);
646 }
647 }
648
649 if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
650 fprintf(stderr, "Bad number of gfx cards (-Z).\n");
651 exit(1);
652 }
653
654 if (m->bintrans_enable && m->arch == ARCH_MIPS) {
655 m->speed_tricks = 0;
656 /* TODO: Print a warning about this? */
657 }
658
659 if (m->n_breakpoints > 0 &&
660 m->bintrans_enable && m->arch == ARCH_MIPS) {
661 fprintf(stderr, "Breakpoints and MIPS binary translation "
662 "don't work too well together right now.\n");
663 exit(1);
664 }
665
666 #ifndef BINTRANS
667 if (m->bintrans_enable) {
668 fprintf(stderr, "WARNING: %s was compiled without "
669 "bintrans support. Ignoring -b.\n", progname);
670 m->bintrans_enable = 0;
671 }
672 #endif
673
674 #ifndef WITH_X11
675 if (m->use_x11) {
676 fprintf(stderr, "WARNING: %s was compiled without "
677 "X11 support. Ignoring -X.\n", progname);
678 m->use_x11 = 0;
679 }
680 #endif
681
682 if (!using_switch_Z && !m->use_x11)
683 m->n_gfx_cards = 0;
684
685 m->bintrans_enabled_from_start = m->bintrans_enable;
686
687 return 0;
688 }
689
690
691 /*
692 * main():
693 *
694 * Two kinds of emulations are started from here:
695 *
696 * o) Simple emulations, using command line arguments, compatible with
697 * earlier version of GXemul/mips64emul.
698 *
699 * o) Emulations set up by parsing special config files. (0 or more.)
700 */
701 int main(int argc, char *argv[])
702 {
703 struct emul **emuls;
704 char **diskimages = NULL;
705 int n_diskimages = 0;
706 int n_emuls;
707 int i;
708
709 progname = argv[0];
710
711 console_init();
712 cpu_init();
713 device_init();
714 machine_init();
715 useremul_init();
716
717 emuls = malloc(sizeof(struct emul *));
718 if (emuls == NULL) {
719 fprintf(stderr, "out of memory\n");
720 exit(1);
721 }
722
723 /* Allocate space for a simple emul setup: */
724 n_emuls = 1;
725 emuls[0] = emul_new(NULL);
726 if (emuls[0] == NULL) {
727 fprintf(stderr, "out of memory\n");
728 exit(1);
729 }
730
731 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
732
733 if (!fully_deterministic) {
734 /* TODO: More than just time(). Use gettimeofday(). */
735 srandom(time(NULL) ^ (getpid() << 12));
736 } else {
737 /* Fully deterministic. -I must have been supplied. */
738 if (emuls[0]->machines[0]->automatic_clock_adjustment) {
739 fatal("Cannot have -D without -I.\n");
740 exit(1);
741 }
742 }
743
744 /* Print startup message: */
745 debug("GXemul");
746 #ifdef VERSION
747 debug("-" VERSION);
748 #endif
749 debug(" Copyright (C) 2003-2005 Anders Gavare\n");
750 debug("Read the source code and/or documentation for "
751 "other Copyright messages.\n\n");
752
753 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE)
754 n_emuls --;
755 else {
756 for (i=0; i<n_diskimages; i++)
757 diskimage_add(emuls[0]->machines[0], diskimages[i]);
758 }
759
760 /* Simple initialization, from command line arguments: */
761 if (n_emuls > 0) {
762 /* Make sure that there are no configuration files as well: */
763 for (i=1; i<argc; i++)
764 if (argv[i][0] == '@') {
765 fprintf(stderr, "You can either start one "
766 "emulation with one machine directly from "
767 "the command\nline, or start one or more "
768 "emulations using configuration files."
769 " Not both.\n");
770 exit(1);
771 }
772
773 /* Initialize one emul: */
774 emul_simple_init(emuls[0]);
775 }
776
777 /* Initialize emulations from config files: */
778 for (i=1; i<argc; i++) {
779 if (argv[i][0] == '@') {
780 char *s = argv[i] + 1;
781 if (strlen(s) == 0 && i+1 < argc &&
782 argv[i+1][0] != '@') {
783 i++;
784 s = argv[i];
785 }
786 n_emuls ++;
787 emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
788 if (emuls == NULL) {
789 fprintf(stderr, "out of memory\n");
790 exit(1);
791 }
792 emuls[n_emuls - 1] =
793 emul_create_from_configfile(s);
794
795 /* Always allow slave xterms when using multiple
796 emulations: */
797 console_allow_slaves(1);
798 }
799 }
800
801 if (n_emuls == 0) {
802 fprintf(stderr, "No emulations defined. Maybe you forgot to "
803 "use -E xx and/or -e yy, to specify\nthe machine type."
804 " For example:\n\n %s -e 3max -d disk.img\n\n"
805 "to boot an emulated DECstation 5000/200 with a disk "
806 "image.\n", progname);
807 exit(1);
808 }
809
810 device_set_exit_on_error(0);
811 console_warn_if_slaves_are_needed();
812
813 /* Run all emulations: */
814 emul_run(emuls, n_emuls);
815
816 return 0;
817 }
818

  ViewVC Help
Powered by ViewVC 1.1.26