usim

Check-in [d36a0d1b29]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix compiler warnings
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA3-256: d36a0d1b29dbd8d6f7c7b5236d6dfad375befe96cd1c67090a67d3c65645cf68
User & Date: nikola 2024-07-01 16:16:17
Context
2024-07-01
16:16
Fix compiler warnings Leaf check-in: d36a0d1b29 user: nikola tags: trunk
2024-06-28
09:34
iob.c (iob_unibus_write, iob_unibus_read): Fix addresses; they are octal. check-in: a7806abc71 user: ams tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.

57
58
59
60
61
62
63
64


65
66
67
68
69
70
71
ucfg.o: ucfg.h ucfg.defs lmch.defs knight.defs

$(USIM_TV_BACKEND) iob.o cadet.o knight.o usim.o: lmch.defs knight.defs

USIM_UCH11 = uch11.o uch11-local.o uch11-chaosd.o uch11-udp.o \
	chutil.o challoc.o chdopen.o chopen.o MINI.o FILE.o glob.o

USIM_OBJS = usim.o ucode.o uexec.o umem.o iob.o mouse.o kbd.o knight.o cadet.o tv.o $(USIM_TV_BACKEND) $(USIM_UCH11) disk.o ini.o ucfg.o trace.o udiss.o usym.o misc.o m32.o idle.o \


	$(CHAOS)/libhosts/libhosts.a
usim: $(USIM_OBJS)
	$(CC) $(CFLAGS) -o $@ $(USIM_OBJS) -lpthread $(LDFLAGS)

READMCR_OBJS = readmcr.o udiss.o misc.o usym.o
readmcr: $(READMCR_OBJS)
	$(CC) $(CFLAGS) -o $@ $(READMCR_OBJS)







|
>
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
ucfg.o: ucfg.h ucfg.defs lmch.defs knight.defs

$(USIM_TV_BACKEND) iob.o cadet.o knight.o usim.o: lmch.defs knight.defs

USIM_UCH11 = uch11.o uch11-local.o uch11-chaosd.o uch11-udp.o \
	chutil.o challoc.o chdopen.o chopen.o MINI.o FILE.o glob.o

USIM_OBJS = usim.o ucode.o uexec.o umem.o iob.o mouse.o kbd.o knight.o cadet.o \
			tv.o $(USIM_TV_BACKEND) $(USIM_UCH11) disk.o ini.o ucfg.o trace.o \
			udiss.o usym.o misc.o m32.o idle.o lmch.o \
	$(CHAOS)/libhosts/libhosts.a
usim: $(USIM_OBJS)
	$(CC) $(CFLAGS) -o $@ $(USIM_OBJS) -lpthread $(LDFLAGS)

READMCR_OBJS = readmcr.o udiss.o misc.o usym.o
readmcr: $(READMCR_OBJS)
	$(CC) $(CFLAGS) -o $@ $(READMCR_OBJS)

Changes to disk.h.

1
2

3
4
5
6
7
8
9
#pragma once


#include <stdint.h>

#define DISKS_MAX 8

struct disk
{
	int fd;


>







1
2
3
4
5
6
7
8
9
10
#pragma once

#include <sys/types.h>
#include <stdint.h>

#define DISKS_MAX 8

struct disk
{
	int fd;

Changes to kbd.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* kbd.c --- keyboard handling */

#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "iob.h"
#include "kbd.h"
#include "cadet.h"
#include "knight.h"
#include "lmch.h"
#include "usim.h"



<
<
<
<







1
2
3




4
5
6
7
8
9
10
/* kbd.c --- keyboard handling */

#include <err.h>





#include "iob.h"
#include "kbd.h"
#include "cadet.h"
#include "knight.h"
#include "lmch.h"
#include "usim.h"

Changes to knight.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define KNIGHT_VANILLA		0	/* VANILLA */
#define KNIGHT_SHIFT		0300	/* SHIFT BITS */
#define KNIGHT_TOP		01400	/* TOP BITS */
#define KNIGHT_CONTROL		06000	/* CONTROL BITS */
#define KNIGHT_META		030000	/* META BITS */
#define KNIGHT_SHIFT_LOCK	040000	/* SHIFT LOCK */

static enum
{
#define X(n, v) KNIGHT_##n = v,
#include "knight.defs"
#undef X
} knight_keysyms;

static unsigned short knight_kbd_map[256];
static unsigned short knight_modifier_map[5];

void
knight_process_bucky(int k, int *extra)
{







|




|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define KNIGHT_VANILLA		0	/* VANILLA */
#define KNIGHT_SHIFT		0300	/* SHIFT BITS */
#define KNIGHT_TOP		01400	/* TOP BITS */
#define KNIGHT_CONTROL		06000	/* CONTROL BITS */
#define KNIGHT_META		030000	/* META BITS */
#define KNIGHT_SHIFT_LOCK	040000	/* SHIFT LOCK */

enum
{
#define X(n, v) KNIGHT_##n = v,
#include "knight.defs"
#undef X
};

static unsigned short knight_kbd_map[256];
static unsigned short knight_modifier_map[5];

void
knight_process_bucky(int k, int *extra)
{

Added lmch.c.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
#include "lmch.h"

struct lmchar_map lmchar_map[LMCH_CODE_LIMIT] = {
#define X(n, v) {STRINGIFY(n), v},
#include "lmch.defs"
#undef X
	{(char *) 0, 0}
};

Changes to lmch.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma once

#include "misc.h"

#define LMCH_CODE_LIMIT 0377

#define LMCH_NoSymbol -1

static enum
{
#define X(n, v) LMCH_##n = v,
#include "lmch.defs"
#undef X
} lmchars;

static struct
{
	char *name;
	int lmchar;
} lmchar_map[LMCH_CODE_LIMIT] = {
#define X(n, v) {STRINGIFY(n), v},
#include "lmch.defs"
#undef X
	{(char *) 0, 0}
};








|




|

|



|
<
<
<
<
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20





#pragma once

#include "misc.h"

#define LMCH_CODE_LIMIT 0377

#define LMCH_NoSymbol -1

enum
{
#define X(n, v) LMCH_##n = v,
#include "lmch.defs"
#undef X
};

extern struct lmchar_map
{
	char *name;
	int lmchar;
} lmchar_map[LMCH_CODE_LIMIT];





Changes to sdl2.c.

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
cadet_allup_key(void)
{
	bool allup;
	int mods;
	int shifts;

	int statesize;
	Uint8 *state;

	allup = true;
	mods = 0;
	shifts = 0;

	state = SDL_GetKeyboardState(&statesize);
	for (int i = 0; allup && i < statesize; i++) {







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
cadet_allup_key(void)
{
	bool allup;
	int mods;
	int shifts;

	int statesize;
	const Uint8 *state;

	allup = true;
	mods = 0;
	shifts = 0;

	state = SDL_GetKeyboardState(&statesize);
	for (int i = 0; allup && i < statesize; i++) {
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//      SDLKey keycode;

	int bi;
	int keysym;

	idle_keyboard_activity();
	keysym = sdl2_keysym_to_xk(e);
	if (keysym == XK_VoidSymbol || keysym > NELEM(kbd_map)) {
		NOTICE(TRACE_USIM, "cadet@sdl2): unable to translate to keysym (keysym = 0%o)\n", keysym);
		return;
	}
	if (kbd_type == 0) {
		if (!keydown)
			return;
		bi = 0;







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//      SDLKey keycode;

	int bi;
	int keysym;

	idle_keyboard_activity();
	keysym = sdl2_keysym_to_xk(e);
	if (keysym == XK_VoidSymbol || keysym > (int)NELEM(kbd_map)) {
		NOTICE(TRACE_USIM, "cadet@sdl2): unable to translate to keysym (keysym = 0%o)\n", keysym);
		return;
	}
	if (kbd_type == 0) {
		if (!keydown)
			return;
		bi = 0;
220
221
222
223
224
225
226




227
228
229
230
231
232
233
		cadet_process_key(keysym /* xk_keysym */ , bi, keydown, &cadet_allup_key);
	}
}

void
update(int u_minh, int u_minv, int hs, int vs)
{




	SDL_UpdateTexture(texture, NULL, tv_bitmap, tv_width * sizeof(Uint32));
	// Flush
	SDL_RenderClear(renderer);
	SDL_RenderCopy(renderer, texture, NULL, NULL);
	SDL_RenderPresent(renderer);
}








>
>
>
>







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
		cadet_process_key(keysym /* xk_keysym */ , bi, keydown, &cadet_allup_key);
	}
}

void
update(int u_minh, int u_minv, int hs, int vs)
{
	(void)u_minh;
	(void)u_minv;
	(void)hs;
	(void)vs;
	SDL_UpdateTexture(texture, NULL, tv_bitmap, tv_width * sizeof(Uint32));
	// Flush
	SDL_RenderClear(renderer);
	SDL_RenderCopy(renderer, texture, NULL, NULL);
	SDL_RenderPresent(renderer);
}

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
		}
	}
}

void
sdl2_idle_change_handler(int mode)
{
	static int width = 22, bottom = 2, right = 2;

	switch (mode) {
	case IDLE_IDLE:
//		XSetForeground(display, idle_gc, tv_foreground);
		break;
	case IDLE_WORKING:
//		XSetForeground(display, idle_gc, tv_background);







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
		}
	}
}

void
sdl2_idle_change_handler(int mode)
{
	// static int width = 22, bottom = 2, right = 2;

	switch (mode) {
	case IDLE_IDLE:
//		XSetForeground(display, idle_gc, tv_foreground);
		break;
	case IDLE_WORKING:
//		XSetForeground(display, idle_gc, tv_background);
341
342
343
344
345
346
347

348
349
350
351
352
353
354
	SDL_Delay(duration / 1000);
	SDL_PauseAudio(1);
}

void
sdl2_beep(int v)
{

///XBEEP (MISC-INST-ENTRY %BEEP)
///;;; First argument is half-wavelength, second is duration.  Both are in microseconds.
///;;; M-1 has 2nd argument (duration) which is added to initial time-check
///;;; M-2 contains most recent time check
///;;;     to compute quitting time
///;;; M-C contains 1st argument, the wavelength
///;;; M-4 contains the time at which the next click must be done.







>







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	SDL_Delay(duration / 1000);
	SDL_PauseAudio(1);
}

void
sdl2_beep(int v)
{
	(void)v;
///XBEEP (MISC-INST-ENTRY %BEEP)
///;;; First argument is half-wavelength, second is duration.  Both are in microseconds.
///;;; M-1 has 2nd argument (duration) which is added to initial time-check
///;;; M-2 contains most recent time check
///;;;     to compute quitting time
///;;; M-C contains 1st argument, the wavelength
///;;; M-4 contains the time at which the next click must be done.

Changes to tv.c.

71
72
73
74
75
76
77

78
79
80
81
82
83
84
	tv_csr |= 1 << 4;
	assert_xbus_interrupt();
}

static void
sigalrm_handler(int arg)
{

	tv_post_60hz_interrupt();
}

void
tv_screenshot(char *fn)
{
	char buff[128];







>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
	tv_csr |= 1 << 4;
	assert_xbus_interrupt();
}

static void
sigalrm_handler(int arg)
{
	(void)arg;
	tv_post_60hz_interrupt();
}

void
tv_screenshot(char *fn)
{
	char buff[128];
155
156
157
158
159
160
161

162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
	}
	accumulate_update(h, v, 32, 1);
}

void
tv_xbus_read(uint32_t offset, uint32_t *pv)
{

	*pv = tv_csr;
}

void
tv_xbus_write(uint32_t offset, uint32_t v)
{

	tv_csr = v;
	tv_csr &= ~(1 << 4);

	/*
	 * Handle hardware reverse-video functionality.
	 */
	if ((v & 4) != tv_colorbit) {
		tv_colorbit = v & 4;
		{
			unsigned long temp = tv_foreground;
			tv_foreground = tv_background;
			tv_background = temp;
		}
		tv_colorbit = v & 4;







>






>






|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
	}
	accumulate_update(h, v, 32, 1);
}

void
tv_xbus_read(uint32_t offset, uint32_t *pv)
{
	(void)offset;
	*pv = tv_csr;
}

void
tv_xbus_write(uint32_t offset, uint32_t v)
{
	(void)offset;
	tv_csr = v;
	tv_csr &= ~(1 << 4);

	/*
	 * Handle hardware reverse-video functionality.
	 */
	if ((int)(v & 4) != tv_colorbit) {
		tv_colorbit = v & 4;
		{
			unsigned long temp = tv_foreground;
			tv_foreground = tv_background;
			tv_background = temp;
		}
		tv_colorbit = v & 4;

Changes to uch11-udp.c.

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
		struct pkt_header *ph = (struct pkt_header *) ((char *) op);
		u_short pklen = LENFC_LEN(ph->ph_lenfc);
		u_short offs = sizeof(struct pkt_header) + pklen;
		if (offs % 2)
			offs++;
		struct chaos_hw_trailer *tp = (struct chaos_hw_trailer *) (op + offs);
		u_short hwdest = tp->ch_hw_destaddr;
		u_short cksum = tp->ch_hw_checksum;
		if (hwdest != udp_bridge_chaddr) {
			INFO(TRACE_CHAOS, "chaos: hw trailer dest is %#o should be %#o\n", hwdest, udp_bridge_chaddr);
			tp->ch_hw_destaddr = udp_bridge_chaddr;
		}
		tp->ch_hw_checksum = htons(uch11_checksum(op, size - 2));

		/* Now swap it */
		ntohs_buf((u_short *) op, (u_short *) op, size);

		INFO(TRACE_CHAOS, "chaos: sending %d bytes (pkt size %d)\n", size + sizeof(struct chudp_header), size);
		if ((nb = send(chaosd_fd, (char *) hp, size + sizeof(struct chudp_header), 0)) < 0) {
			perror("chaos: send to udp");
			ERR(TRACE_CHAOS, "chaos: send to udp failed");
			return -1;
		} else if (nb != size + sizeof(struct chudp_header)) {
			ERR(TRACE_CHAOS, "chaos: could not send the full pkt: %d sent, expected %d", nb, size + sizeof(struct chudp_header));
			return -1;
		}
	}
	return 0;
}

int
chaos_poll_udp(void)
{
	/* basically copy chaos_poll_chaosd but skip CHUDP header and swap */
	ssize_t ret;
	struct pollfd pfd[1];
	int nfds, timeout;
	unsigned char lenbytes[4];
	ssize_t len;
	int dest_addr;

	if (hybrid_udp_and_local) {
		/* Prioritize local traffic */
		chaos_poll_local();
	}








|














|














|
|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
		struct pkt_header *ph = (struct pkt_header *) ((char *) op);
		u_short pklen = LENFC_LEN(ph->ph_lenfc);
		u_short offs = sizeof(struct pkt_header) + pklen;
		if (offs % 2)
			offs++;
		struct chaos_hw_trailer *tp = (struct chaos_hw_trailer *) (op + offs);
		u_short hwdest = tp->ch_hw_destaddr;
		// u_short cksum = tp->ch_hw_checksum;
		if (hwdest != udp_bridge_chaddr) {
			INFO(TRACE_CHAOS, "chaos: hw trailer dest is %#o should be %#o\n", hwdest, udp_bridge_chaddr);
			tp->ch_hw_destaddr = udp_bridge_chaddr;
		}
		tp->ch_hw_checksum = htons(uch11_checksum(op, size - 2));

		/* Now swap it */
		ntohs_buf((u_short *) op, (u_short *) op, size);

		INFO(TRACE_CHAOS, "chaos: sending %d bytes (pkt size %d)\n", size + sizeof(struct chudp_header), size);
		if ((nb = send(chaosd_fd, (char *) hp, size + sizeof(struct chudp_header), 0)) < 0) {
			perror("chaos: send to udp");
			ERR(TRACE_CHAOS, "chaos: send to udp failed");
			return -1;
		} else if (nb != size + (int)sizeof(struct chudp_header)) {
			ERR(TRACE_CHAOS, "chaos: could not send the full pkt: %d sent, expected %d", nb, size + sizeof(struct chudp_header));
			return -1;
		}
	}
	return 0;
}

int
chaos_poll_udp(void)
{
	/* basically copy chaos_poll_chaosd but skip CHUDP header and swap */
	ssize_t ret;
	struct pollfd pfd[1];
	int nfds, timeout;
	// unsigned char lenbytes[4];
	// ssize_t len;
	int dest_addr;

	if (hybrid_udp_and_local) {
		/* Prioritize local traffic */
		chaos_poll_local();
	}

Changes to ucode.c.

52
53
54
55
56
57
58

59


60
61
62
63
64
65
66
67
			tv_poll();
		}
		cycles++;
		if (cycles == 0)
			cycles = 1;
		/// Move this to usim.c ...
		if (!prom_enabled_flag) {

			if (full_trace_lc > 0 && (mfmem[1] & 0xffffff) == full_trace_lc && ++full_trace_repeat_counter == 4 && full_trace_last_lc != (mfmem[1] & 0xffffff)) {


				printf("Enabling full tracing at lc #x%x\n", mfmem[1]);
				trace_level = LOG_DEBUG;
				trace_facilities = TRACE_UCODE | TRACE_MICROCODE;
			}
			check_npc_dump();
			full_trace_last_lc = mfmem[1];
		}
		step();







>
|
>
>
|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
			tv_poll();
		}
		cycles++;
		if (cycles == 0)
			cycles = 1;
		/// Move this to usim.c ...
		if (!prom_enabled_flag) {
			if (full_trace_lc > 0
					&& (int)(mfmem[1] & 0xffffff) == full_trace_lc
					&& ++full_trace_repeat_counter == 4
					&& full_trace_last_lc != (int)(mfmem[1] & 0xffffff)) {
				printf("Enabling full tracing at lc #x%lx\n", mfmem[1]);
				trace_level = LOG_DEBUG;
				trace_facilities = TRACE_UCODE | TRACE_MICROCODE;
			}
			check_npc_dump();
			full_trace_last_lc = mfmem[1];
		}
		step();
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
	printf("\n");
}

static void
show_pdl(void)
{
	printf("PDL MEMORY:\n");
	printf("\tPDL POINTER: %o, PDL INDEX: %o\n", mfmem[00014], mfmem[00013]);
	/* *INDENT-OFF* */
	for (int i = 0; i < 1024; i += 4) {
		int skipped;

		printf("\tPDL[%04o] %011o %011o %011o %011o\n", i,
		    pdl[i + 0], pdl[i + 1],
		    pdl[i + 2], pdl[i + 3]);







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	printf("\n");
}

static void
show_pdl(void)
{
	printf("PDL MEMORY:\n");
	printf("\tPDL POINTER: %lo, PDL INDEX: %lo\n", mfmem[00014], mfmem[00013]);
	/* *INDENT-OFF* */
	for (int i = 0; i < 1024; i += 4) {
		int skipped;

		printf("\tPDL[%04o] %011o %011o %011o %011o\n", i,
		    pdl[i + 0], pdl[i + 1],
		    pdl[i + 2], pdl[i + 3]);
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
	fsync(fd);
	close(fd);
}

void
extra_dump_state(char *suffix)	// Rename function, merge with save_state, and allow for a template or extra parameter (int incremenet?).
{
	char buffer[256];
	static int dump_nr = 0;

	snprintf(buffer, 256, "/tmp/usim-%03d-%s.state", dump_nr++, suffix);
	save_state(buffer);
	printf(".. dumped to file %s\n", buffer);
}

int vmem_trace_values[256] = { 0 };

int vmem_trace_index = 0;







|


|







651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
	fsync(fd);
	close(fd);
}

void
extra_dump_state(char *suffix)	// Rename function, merge with save_state, and allow for a template or extra parameter (int incremenet?).
{
	char buffer[512];
	static int dump_nr = 0;

	snprintf(buffer, sizeof buffer, "/tmp/usim-%03d-%s.state", dump_nr++, suffix);
	save_state(buffer);
	printf(".. dumped to file %s\n", buffer);
}

int vmem_trace_values[256] = { 0 };

int vmem_trace_index = 0;

Changes to usim.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
/* usim --- MIT CADR simulator
 */

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "uch11.h"
#include "disk.h"
#include "iob.h"
#include "idle.h"
#include "kbd.h"
#include "tv.h"
#include "ucfg.h"
#include "ucode.h"
#include "usim.h"
#include "utrace.h"

static char *config_filename;
bool dump_state_flag;
bool verbose_dump_state_flag;
bool warm_boot_flag;
symtab_t sym_mcr;
symtab_t sym_prom;

static void
sighup_handler(int arg)
{

	ini_parse(config_filename, ucfg_handler, &ucfg);
}

static void
siginfo_handler(int arg)
{

	dump_state(true);
}

static void
usage(void)
{
	fprintf(stderr, "usage: usim [OPTION]...\n");










<








<











>






>







1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/* usim --- MIT CADR simulator
 */

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


#include "disk.h"
#include "iob.h"
#include "idle.h"
#include "kbd.h"
#include "tv.h"
#include "ucfg.h"
#include "ucode.h"
#include "usim.h"


static char *config_filename;
bool dump_state_flag;
bool verbose_dump_state_flag;
bool warm_boot_flag;
symtab_t sym_mcr;
symtab_t sym_prom;

static void
sighup_handler(int arg)
{
	(void)arg;
	ini_parse(config_filename, ucfg_handler, &ucfg);
}

static void
siginfo_handler(int arg)
{
	(void)arg;
	dump_state(true);
}

static void
usage(void)
{
	fprintf(stderr, "usage: usim [OPTION]...\n");