/[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 14 - (show annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 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 /*
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.244 2005/09/07 07:41:29 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 fprintf(stderr, "Invalid scaledown value.\n");
518 exit(1);
519 }
520 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 fprintf(stderr, "Run %s -h for help on command "
551 "line options.\n", progname);
552 exit(1);
553 }
554 }
555
556 if (type != NULL || subtype != NULL) {
557 if (type == NULL)
558 type = "";
559 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 /* -i and -r are pretty verbose: */
582
583 if (m->instruction_trace && !verbose) {
584 fprintf(stderr, "Implicitly %sturning on -v, because"
585 " of -i\n", quiet_mode? "turning off -q and " : "");
586 verbose = 1;
587 quiet_mode = 0;
588 }
589
590 if (m->register_dump && !verbose) {
591 fprintf(stderr, "Implicitly %sturning on -v, because"
592 " of -r\n", quiet_mode? "turning off -q and " : "");
593 verbose = 1;
594 quiet_mode = 0;
595 }
596
597 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
603
604 /*
605 * Usually, an executable filename must be supplied.
606 *
607 * However, it is possible to boot directly from a harddisk image
608 * file. If no kernel is supplied, but a diskimage is being used,
609 * then try to boot from disk.
610 */
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 if (m->n_breakpoints > 0 &&
655 m->bintrans_enable && m->arch == ARCH_MIPS) {
656 fprintf(stderr, "Breakpoints and MIPS binary translation "
657 "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 char **diskimages = NULL;
700 int n_diskimages = 0;
701 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 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
727
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 else {
751 for (i=0; i<n_diskimages; i++)
752 diskimage_add(emuls[0]->machines[0], diskimages[i]);
753 }
754
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 fprintf(stderr, "No emulations defined. Maybe you forgot to "
798 "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 "to boot an emulated DECstation 5000/200 with a disk "
801 "image.\n", progname);
802 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