/[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 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 23473 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26