/[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 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 23321 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26