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

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


1 /*
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.243 2005/08/07 17:42:02 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