/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22228 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26