1/*	$NetBSD: ncr53cxxx.c,v 1.15 2005/12/11 12:22:36 christos Exp $	*/
2
3/*
4 * Copyright (c) 1995,1999 Michael L. Hitch
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*	ncr53cxxx.c	- SCSI SCRIPTS Assembler		*/
29
30#include <sys/cdefs.h>
31__RCSID("$NetBSD: ncr53cxxx.c,v 1.15 2005/12/11 12:22:36 christos Exp $");
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <time.h>
37
38#ifndef AMIGA
39#define strcmpi	strcasecmp
40#endif
41
42#define	MAXTOKENS	16
43#define	MAXINST		1024
44#define	MAXSYMBOLS	128
45
46struct {
47	int	type;
48	char	*name;
49} tokens[MAXTOKENS];
50int	ntokens;
51int	tokenix;
52
53void	f_proc (void);
54void	f_pass (void);
55void	f_list (void);		/* ENTRY, EXTERNAL label list */
56void	f_define (void);	/* ABSOLUTE, RELATIVE label list */
57void	f_move (void);
58void	f_jump (void);
59void	f_call (void);
60void	f_return (void);
61void	f_int (void);
62void	f_intfly (void);
63void	f_select (void);
64void	f_reselect (void);
65void	f_wait (void);
66void	f_disconnect (void);
67void	f_set (void);
68void	f_clear (void);
69void	f_load (void);
70void	f_store (void);
71void	f_nop (void);
72void	f_arch (void);
73
74struct {
75	char	*name;
76	void	(*func)(void);
77} directives[] = {
78	{"PROC",	f_proc},
79	{"PASS",	f_pass},
80	{"ENTRY",	f_list},
81	{"ABSOLUTE",	f_define},
82	{"EXTERN",	f_list},
83	{"EXTERNAL",	f_list},
84	{"RELATIVE",	f_define},
85	{"MOVE",	f_move},
86	{"JUMP",	f_jump},
87	{"CALL",	f_call},
88	{"RETURN",	f_return},
89	{"INT",		f_int},
90	{"INTFLY",	f_intfly},
91	{"SELECT",	f_select},
92	{"RESELECT",	f_reselect},
93	{"WAIT",	f_wait},
94	{"DISCONNECT",	f_disconnect},
95	{"SET",		f_set},
96	{"CLEAR",	f_clear},
97	{"LOAD",	f_load},
98	{"STORE",	f_store},
99	{"NOP",		f_nop},
100	{"ARCH",	f_arch},
101	{NULL, NULL}};
102
103u_int32_t script[MAXINST];
104int	dsps;
105char	*script_name = "SCRIPT";
106u_int32_t inst0, inst1, inst2;
107unsigned int	ninsts;
108unsigned int	npatches;
109
110struct patchlist {
111	struct patchlist *next;
112	unsigned	offset;
113} *patches;
114
115#define	S_LABEL		0x0000
116#define	S_ABSOLUTE	0x0001
117#define	S_RELATIVE	0x0002
118#define	S_EXTERNAL	0x0003
119#define	F_DEFINED	0x0001
120#define	F_ENTRY		0x0002
121struct {
122	short	type;
123	short	flags;
124	u_int32_t value;
125	struct patchlist *patchlist;
126	char	*name;
127} symbols[MAXSYMBOLS];
128int nsymbols;
129
130char	*stypes[] = {"Label", "Absolute", "Relative", "External"};
131
132char	*phases[] = {
133	"data_out", "data_in", "cmd", "status",
134	"res4", "res5", "msg_out", "msg_in"
135};
136
137struct ncrregs {
138	char *name;
139	int addr[5];
140};
141#define ARCH700 1
142#define ARCH710 2
143#define ARCH720 3
144#define ARCH810 4
145#define ARCH825 5
146
147struct ncrregs 	regs[] = {
148	{"scntl0",	{0x00, 0x00, 0x00, 0x00, 0x00}},
149	{"scntl1",	{0x01, 0x01, 0x01, 0x01, 0x01}},
150	{"sdid",	{0x02, 0x02,   -1,   -1,   -1}},
151	{"sien",	{0x03, 0x03,   -1,   -1,   -1}},
152	{"scid",	{0x04, 0x04,   -1,   -1,   -1}},
153	{"scntl2",	{  -1,   -1, 0x02, 0x02, 0x02}},
154	{"scntl3",	{  -1,   -1, 0x03, 0x03, 0x03}},
155	{"scid", 	{  -1,   -1, 0x04, 0x04, 0x04}},
156	{"sxfer",	{0x05, 0x05, 0x05, 0x05, 0x05}},
157	{"sodl",	{0x06, 0x06,   -1,   -1,   -1}},
158	{"socl",	{0x07, 0x07,   -1,   -1,   -1}},
159	{"sdid",	{  -1,   -1, 0x06, 0x06, 0x06}},
160	{"gpreg",	{  -1,   -1, 0x07, 0x07, 0x07}},
161	{"sfbr",	{0x08, 0x08, 0x08, 0x08, 0x08}},
162	{"sidl",	{0x09, 0x09,   -1,   -1,   -1}},
163	{"sbdl",	{0x0a, 0x0a,   -1,   -1,   -1}},
164	{"socl",	{  -1,   -1, 0x09, 0x09, 0x09}},
165	{"ssid", 	{  -1,   -1, 0x0a, 0x0a, 0x0a}},
166	{"sbcl",	{0x0b, 0x0b, 0x0b, 0x0b, 0x0b}},
167	{"dstat",	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c}},
168	{"sstat0",	{0x0d, 0x0d, 0x0d, 0x0d, 0x0d}},
169	{"sstat1",	{0x0e, 0x0e, 0x0e, 0x0e, 0x0e}},
170	{"sstat2",	{0x0f, 0x0f, 0x0f, 0x0f, 0x0f}},
171	{"dsa0",	{  -1, 0x10, 0x10, 0x10, 0x10}},
172	{"dsa1",	{  -1, 0x11, 0x11, 0x11, 0x11}},
173	{"dsa2",	{  -1, 0x12, 0x12, 0x12, 0x12}},
174	{"dsa3",	{  -1, 0x13, 0x13, 0x13, 0x13}},
175	{"ctest0",	{0x14, 0x14, 0x18, 0x18, 0x18}},
176	{"ctest1",	{0x15, 0x15, 0x19, 0x19, 0x19}},
177	{"ctest2",	{0x16, 0x16, 0x1a, 0x1a, 0x1a}},
178	{"ctest3",	{0x17, 0x17, 0x1b, 0x1b, 0x1b}},
179	{"ctest4",	{0x18, 0x18, 0x21, 0x21, 0x21}},
180	{"ctest5",	{0x19, 0x19, 0x22, 0x22, 0x22}},
181	{"ctest6",	{0x1a, 0x1a, 0x23, 0x23, 0x23}},
182	{"ctest7",	{0x1b, 0x1b,   -1,   -1,   -1}},
183	{"temp0",	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c}},
184	{"temp1",	{0x1d, 0x1d, 0x1d, 0x1d, 0x1d}},
185	{"temp2", 	{0x1e, 0x1e, 0x1e, 0x1e, 0x1e}},
186	{"temp3",	{0x1f, 0x1f, 0x1f, 0x1f, 0x1f}},
187	{"dfifo",	{0x20, 0x20, 0x20, 0x20, 0x20}},
188	{"istat", 	{0x21, 0x21, 0x14, 0x14, 0x14}},
189	{"ctest8",	{0x22, 0x22,   -1,   -1,   -1}},
190	{"lcrc",	{  -1, 0x23,   -1,   -1,   -1}},
191	{"ctest9",	{0x23,   -1,   -1,   -1,   -1}},
192	{"dbc0",	{0x24, 0x24, 0x24, 0x24, 0x24}},
193	{"dbc1",	{0x25, 0x25, 0x25, 0x25, 0x25}},
194	{"dbc2",	{0x26, 0x26, 0x26, 0x26, 0x26}},
195	{"dcmd",	{0x27, 0x27, 0x27, 0x27, 0x27}},
196	{"dnad0",	{0x28, 0x28, 0x28, 0x28, 0x28}},
197	{"dnad1",	{0x29, 0x29, 0x29, 0x29, 0x29}},
198	{"dnad2",	{0x2a, 0x2a, 0x2a, 0x2a, 0x2a}},
199	{"dnad3",	{0x2b, 0x2b, 0x2b, 0x2b, 0x2b}},
200	{"dsp0",	{0x2c, 0x2c, 0x2c, 0x2c, 0x2c}},
201	{"dsp1",	{0x2d, 0x2d, 0x2d, 0x2d, 0x2d}},
202	{"dsp2",	{0x2e, 0x2e, 0x2e, 0x2e, 0x2e}},
203	{"dsp3",	{0x2f, 0x2f, 0x2f, 0x2f, 0x2f}},
204	{"dsps0",	{0x30, 0x30, 0x30, 0x30, 0x30}},
205	{"dsps1",	{0x31, 0x31, 0x31, 0x31, 0x31}},
206	{"dsps2",	{0x32, 0x32, 0x32, 0x32, 0x32}},
207	{"dsps3",	{0x33, 0x33, 0x33, 0x33, 0x33}},
208	{"scratch0",	{  -1, 0x34,   -1,   -1,   -1}},
209	{"scratch1",	{  -1, 0x35,   -1,   -1,   -1}},
210	{"scratch2",	{  -1, 0x36,   -1,   -1,   -1}},
211	{"scratch3",	{  -1, 0x37,   -1,   -1,   -1}},
212	{"scratcha0",	{0x10,   -1, 0x34, 0x34, 0x34}},
213	{"scratcha1",	{0x11,   -1, 0x35, 0x35, 0x35}},
214	{"scratcha2",	{0x12,   -1, 0x36, 0x36, 0x36}},
215	{"scratcha3",	{0x13,   -1, 0x37, 0x37, 0x37}},
216	{"dmode",	{0x34, 0x38, 0x38, 0x38, 0x38}},
217	{"dien",	{0x39, 0x39, 0x39, 0x39, 0x39}},
218	{"dwt",		{0x3a, 0x3a, 0x3a,   -1,   -1}},
219	{"sbr",		{  -1,   -1,   -1, 0x3a, 0x3a}},
220	{"dcntl",	{0x3b, 0x3b, 0x3b, 0x3b, 0x3b}},
221	{"addr0",	{  -1, 0x3c, 0x3c, 0x3c, 0x3c}},
222	{"addr1",	{  -1, 0x3d, 0x3d, 0x3d, 0x3d}},
223	{"addr2",	{  -1, 0x3e, 0x3e, 0x3e, 0x3e}},
224	{"addr3",	{  -1, 0x3f, 0x3f, 0x3f, 0x3f}},
225	{"sien0",	{  -1,   -1, 0x40, 0x40, 0x40}},
226	{"sien1",	{  -1,   -1, 0x41, 0x41, 0x41}},
227	{"sist0",	{  -1,   -1, 0x42, 0x42, 0x42}},
228	{"sist1",	{  -1,   -1, 0x43, 0x43, 0x43}},
229	{"slpar",	{  -1,   -1, 0x44, 0x44, 0x44}},
230	{"swide",	{  -1,   -1, 0x45,   -1, 0x45}},
231	{"macntl",	{  -1,   -1, 0x46, 0x46, 0x46}},
232	{"gpcntl",	{  -1,   -1, 0x47, 0x47, 0x47}},
233	{"stime0",	{  -1,   -1, 0x48, 0x48, 0x48}},
234	{"stime1",	{  -1,   -1, 0x49, 0x49, 0x49}},
235	{"respid0",	{  -1,   -1, 0x4a, 0x4a, 0x4a}},
236	{"respid1",	{  -1,   -1, 0x4b,   -1, 0x4b}},
237	{"stest0",	{  -1,   -1, 0x4c, 0x4c, 0x4c}},
238	{"stest1",	{  -1,   -1, 0x4d, 0x4d, 0x4d}},
239	{"stest2",	{  -1,   -1, 0x4e, 0x4e, 0x4e}},
240	{"stest3",	{  -1,   -1, 0x4f, 0x4f, 0x4f}},
241	{"sidl0",	{  -1,   -1, 0x50, 0x50, 0x50}},
242	{"sidl1",	{  -1,   -1, 0x51,   -1, 0x51}},
243	{"sodl0",	{  -1,   -1, 0x54, 0x54, 0x54}},
244	{"sodl1",	{  -1,   -1, 0x55,   -1, 0x55}},
245	{"sbdl0",	{  -1,   -1, 0x58, 0x58, 0x58}},
246	{"sbdl1",	{  -1,   -1, 0x59,   -1, 0x59}},
247	{"scratchb0",	{0x3c,   -1, 0x5c, 0x5c, 0x5c}},
248	{"scratchb1",	{0x3d,   -1, 0x5d, 0x5d, 0x5d}},
249	{"scratchb2",	{0x3e,   -1, 0x5e, 0x5e, 0x5e}},
250	{"scratchb3",	{0x3f,   -1, 0x5f, 0x5f, 0x5f}},
251	{"scratchc0",	{  -1,   -1,   -1,   -1, 0x60}},
252	{"scratchc1",	{  -1,   -1,   -1,   -1, 0x61}},
253	{"scratchc2",	{  -1,   -1,   -1,   -1, 0x62}},
254	{"scratchc3",	{  -1,   -1,   -1,   -1, 0x63}},
255	{"scratchd0",	{  -1,   -1,   -1,   -1, 0x64}},
256	{"scratchd1",	{  -1,   -1,   -1,   -1, 0x65}},
257	{"scratchd2",	{  -1,   -1,   -1,   -1, 0x66}},
258	{"scratchd3",	{  -1,   -1,   -1,   -1, 0x67}},
259	{"scratche0",	{  -1,   -1,   -1,   -1, 0x68}},
260	{"scratche1",	{  -1,   -1,   -1,   -1, 0x69}},
261	{"scratche2",	{  -1,   -1,   -1,   -1, 0x6a}},
262	{"scratche3",	{  -1,   -1,   -1,   -1, 0x6b}},
263	{"scratchf0",	{  -1,   -1,   -1,   -1, 0x6c}},
264	{"scratchf1",	{  -1,   -1,   -1,   -1, 0x6d}},
265	{"scratchf2",	{  -1,   -1,   -1,   -1, 0x6e}},
266	{"scratchf3",	{  -1,   -1,   -1,   -1, 0x6f}},
267	{"scratchg0",	{  -1,   -1,   -1,   -1, 0x70}},
268	{"scratchg1",	{  -1,   -1,   -1,   -1, 0x71}},
269	{"scratchg2",	{  -1,   -1,   -1,   -1, 0x72}},
270	{"scratchg3",	{  -1,   -1,   -1,   -1, 0x73}},
271	{"scratchh0",	{  -1,   -1,   -1,   -1, 0x74}},
272	{"scratchh1",	{  -1,   -1,   -1,   -1, 0x75}},
273	{"scratchh2",	{  -1,   -1,   -1,   -1, 0x7e}},
274	{"scratchh3",	{  -1,   -1,   -1,   -1, 0x77}},
275	{"scratchi0",	{  -1,   -1,   -1,   -1, 0x78}},
276	{"scratchi1",	{  -1,   -1,   -1,   -1, 0x79}},
277	{"scratchi2",	{  -1,   -1,   -1,   -1, 0x7a}},
278	{"scratchi3",	{  -1,   -1,   -1,   -1, 0x7b}},
279	{"scratchj0",	{  -1,   -1,   -1,   -1, 0x7c}},
280	{"scratchj1",	{  -1,   -1,   -1,   -1, 0x7d}},
281	{"scratchj2",	{  -1,   -1,   -1,   -1, 0x7e}},
282	{"scratchj3",	{  -1,   -1,   -1,   -1, 0x7f}},
283};
284
285int	lineno;
286int	err_listed;
287int	arch;
288int	partial_flag;
289
290char	inbuf[128];
291
292char	*sourcefile;
293char	*outputfile;
294char	*listfile;
295char	*errorfile;
296
297FILE	*infp;
298FILE	*outfp;
299FILE	*listfp;
300FILE	*errfp;
301
302void	setarch(char *);
303void	parse (void);
304void	process (void);
305void	emit_symbols (void);
306void	list_symbols (void);
307void	errout (char *);
308void	define_symbol (char *, u_int32_t, short, short);
309void	patch_label (void);
310void	close_script (void);
311void	new_script (char *);
312void	store_inst (void);
313int	expression (int *);
314int	evaluate (int);
315int	number (char *);
316int	lookup (char *);
317int	reserved (char *, int);
318int	CheckPhase (int);
319int	CheckRegister (int);
320void	transfer (int, int);
321void	select_reselect (int);
322void	set_clear (u_int32_t);
323void	block_move (void);
324void	register_write (void);
325void	memory_to_memory (void);
326void	loadstore (int);
327void	error_line(void);
328char	*makefn(char *, char *);
329void	usage(void);
330
331int
332main (int argc, char *argv[])
333{
334	int	i;
335	struct patchlist *p;
336
337	if (argc < 2 || argv[1][0] == '-')
338		usage();
339	sourcefile = argv[1];
340	infp = fopen (sourcefile, "r");
341	if (infp == NULL) {
342		perror ("open source");
343		fprintf (stderr, "scc: error opening source file %s\n", argv[1]);
344		exit (1);
345	}
346	/*
347	 * process options
348	 * -l [listfile]
349	 * -o [outputfile]
350	 * -p [outputfile]
351	 * -z [debugfile]
352	 * -e [errorfile]
353	 * -a arch
354	 * -v
355	 * -u
356	 */
357	for (i = 2; i < argc; ++i) {
358		if (argv[i][0] != '-')
359			usage();
360		switch (argv[i][1]) {
361		case 'o':
362		case 'p':
363			partial_flag = argv[i][1] == 'p';
364			if (i + 1 >= argc || argv[i + 1][0] == '-')
365				outputfile = makefn (sourcefile, "out");
366			else {
367				outputfile = argv[i + 1];
368				++i;
369			}
370			break;
371		case 'l':
372			if (i + 1 >= argc || argv[i + 1][0] == '-')
373				listfile = makefn (sourcefile, "lis");
374			else {
375				listfile = argv[i + 1];
376				++i;
377			}
378			break;
379		case 'e':
380			if (i + 1 >= argc || argv[i + 1][0] == '-')
381				errorfile = makefn (sourcefile, "err");
382			else {
383				errorfile = argv[i + 1];
384				++i;
385			}
386			break;
387		case 'a':
388			if (i + 1 == argc)
389				usage();
390			setarch(argv[i +1]);
391			if (arch == 0) {
392				fprintf(stderr,"%s: bad arch '%s'\n",
393					argv[0], argv[i +1]);
394				exit(1);
395			}
396			++i;
397			break;
398		default:
399			fprintf (stderr, "scc: unrecognized option '%c'\n",
400			    argv[i][1]);
401			usage();
402		}
403	}
404	if (outputfile)
405		outfp = fopen (outputfile, "w");
406	if (listfile)
407		listfp = fopen (listfile, "w");
408	if (errorfile)
409		errfp = fopen (errorfile, "w");
410	else
411		errfp = stderr;
412
413	if (outfp) {
414		time_t cur_time;
415
416		fprintf(outfp, "/*\t$NetBSD: ncr53cxxx.c,v 1.15 2005/12/11 12:22:36 christos Exp $\t*/\n");
417		fprintf(outfp, "/*\n");
418		fprintf(outfp, " *\tDO NOT EDIT - this file is automatically generated.\n");
419		time(&cur_time);
420		fprintf(outfp, " *\tcreated from %s on %s", sourcefile, ctime(&cur_time));
421		fprintf(outfp, " */\n");
422	}
423
424	while (fgets (inbuf, sizeof (inbuf), infp)) {
425		++lineno;
426		if (listfp)
427			fprintf (listfp, "%3d:  %s", lineno, inbuf);
428		err_listed = 0;
429		parse ();
430		if (ntokens) {
431#ifdef DUMP_TOKENS
432			int	i;
433
434			fprintf (listfp, "      %d tokens\n", ntokens);
435			for (i = 0; i < ntokens; ++i) {
436				fprintf (listfp, "      %d: ", i);
437				if (tokens[i].type)
438					fprintf (listfp,"'%c'\n", tokens[i].type);
439				else
440					fprintf (listfp, "%s\n", tokens[i].name);
441			}
442#endif
443			if (ntokens >= 2 && tokens[0].type == 0 &&
444			    tokens[1].type == ':') {
445			    	define_symbol (tokens[0].name, dsps, S_LABEL, F_DEFINED);
446				tokenix += 2;
447			}
448			if (tokenix < ntokens)
449				process ();
450		}
451
452	}
453	close_script ();
454	emit_symbols ();
455	if (outfp && !partial_flag) {
456		fprintf (outfp, "\nu_int32_t INSTRUCTIONS = 0x%08x;\n", ninsts);
457		fprintf (outfp, "u_int32_t PATCHES = 0x%08x;\n", npatches);
458		fprintf (outfp, "u_int32_t LABELPATCHES[] = {\n");
459		p = patches;
460		while (p) {
461			fprintf (outfp, "\t0x%08x,\n", p->offset / 4);
462			p = p->next;
463		}
464		fprintf (outfp, "};\n\n");
465	}
466	list_symbols ();
467	exit(0);
468}
469
470void setarch(char *val)
471{
472	switch (atoi(val)) {
473	case 700:
474		arch = ARCH700;
475		break;
476	case 710:
477		arch = ARCH710;
478		break;
479	case 720:
480		arch = ARCH720;
481		break;
482	case 810:
483		arch = ARCH810;
484		break;
485	case 825:
486		arch = ARCH825;
487		break;
488	default:
489		arch = 0;
490	}
491}
492
493void emit_symbols ()
494{
495	int	i;
496	struct	patchlist *p;
497
498	if (nsymbols == 0 || outfp == NULL)
499		return;
500
501	for (i = 0; i < nsymbols; ++i) {
502		char	*code;
503		if ((symbols[i].flags & F_DEFINED) == 0 &&
504		    symbols[i].type != S_EXTERNAL) {
505			fprintf(stderr, "warning: symbol %s undefined\n",
506			    symbols[i].name);
507		}
508		if (symbols[i].type == S_ABSOLUTE)
509			code = "A_";
510		else if (symbols[i].type == S_RELATIVE)
511			code = "R_";
512		else if (symbols[i].type == S_EXTERNAL)
513			code = "E_";
514		else if (symbols[i].flags & F_ENTRY)
515			code = "Ent_";
516		else
517			continue;
518		fprintf (outfp, "#define\t%s%s\t0x%08x\n", code, symbols[i].name,
519			symbols[i].value);
520		if (symbols[i].flags & F_ENTRY || symbols[i].patchlist == NULL)
521			continue;
522		fprintf (outfp, "u_int32_t %s%s_Used[] = {\n", code, symbols[i].name);
523#if 1
524		p = symbols[i].patchlist;
525		while (p) {
526			fprintf (outfp, "\t0x%08x,\n", p->offset / 4);
527			p = p->next;
528		}
529#endif
530		fprintf (outfp, "};\n\n");
531	}
532	/* patches ? */
533}
534
535void list_symbols ()
536{
537	int	i;
538
539	if (nsymbols == 0 || listfp == NULL)
540		return;
541	fprintf (listfp, "\n\nValue     Type     Symbol\n");
542	for (i = 0; i < nsymbols; ++i) {
543		fprintf (listfp, "%08x: %-8s %s\n", symbols[i].value,
544			stypes[symbols[i].type], symbols[i].name);
545	}
546}
547
548void errout (char *text)
549{
550	error_line();
551	fprintf (errfp, "*** %s ***\n", text);
552}
553
554void parse ()
555{
556	char *p = inbuf;
557	char c;
558	char string[64];
559	char *s;
560
561	ntokens = tokenix = 0;
562	while (1) {
563		while ((c = *p++) && c != '\n' && (c <= ' ' || c == '\t'))
564			;
565		if (c == '\n' || c == 0 || c == ';')
566			break;
567		if (ntokens >= MAXTOKENS) {
568			errout ("Token table full");
569			break;
570		}
571		if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
572		    (c >= 'A' && c <= 'Z') || c == '$' || c == '_') {
573		    	s = string;
574		    	*s++ = c;
575		    	while (((c = *p) >= '0' && c <= '9') ||
576		    	    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
577		    	    c == '_' || c == '$') {
578		    	    	*s++ = *p++;
579		    	}
580		    	*s = 0;
581		    	tokens[ntokens].name = malloc (strlen (string) + 1);
582		    	strcpy (tokens[ntokens].name, string);
583		    	tokens[ntokens].type = 0;
584		}
585		else {
586			tokens[ntokens].type = c;
587		}
588		++ntokens;
589	}
590	return;
591}
592
593void	process ()
594{
595	int	i;
596
597	if (tokens[tokenix].type) {
598		error_line();
599		fprintf (errfp, "Error: expected directive, found '%c'\n",
600			tokens[tokenix].type);
601		return;
602	}
603	for (i = 0; directives[i].name; ++i) {
604		if (strcmpi (directives[i].name, tokens[tokenix].name) == 0)
605			break;
606	}
607	if (directives[i].name == NULL) {
608		error_line();
609		fprintf (errfp, "Error: expected directive, found \"%s\"\n",
610			tokens[tokenix].name);
611		return;
612	}
613	if (directives[i].func == NULL) {
614		error_line();
615		fprintf (errfp, "No function for directive \"%s\"\n", tokens[tokenix].name);
616	} else {
617#if 0
618		fprintf (listfp, "Processing directive \"%s\"\n", directives[i].name);
619#endif
620		++tokenix;
621		(*directives[i].func) ();
622	}
623}
624
625void define_symbol (char *name, u_int32_t value, short type, short flags)
626{
627	int	i;
628	struct patchlist *p;
629
630	for (i = 0; i < nsymbols; ++i) {
631		if (symbols[i].type == type && strcmp (symbols[i].name, name) == 0) {
632			if (symbols[i].flags & F_DEFINED) {
633				error_line();
634				fprintf (errfp, "*** Symbol \"%s\" multiply defined\n",
635					name);
636			} else {
637				symbols[i].flags |= flags;
638				symbols[i].value = value;
639				p = symbols[i].patchlist;
640				while (p) {
641					if (p->offset > dsps)
642						errout ("Whoops\007");
643					else
644						script[p->offset / 4] += dsps;
645					p = p->next;
646				}
647			}
648			return;
649		}
650	}
651	if (nsymbols >= MAXSYMBOLS) {
652		errout ("Symbol table full");
653		return;
654	}
655	symbols[nsymbols].type = type;
656	symbols[nsymbols].flags = flags;
657	symbols[nsymbols].value = value;
658	symbols[nsymbols].patchlist = NULL;
659	symbols[nsymbols].name = malloc (strlen (name) + 1);
660	strcpy (symbols[nsymbols].name, name);
661	++nsymbols;
662}
663
664void patch_label (void)
665{
666	struct patchlist *p, **h;
667
668	h = &patches;
669	while(*h)
670		h = &(*h)->next;
671	p = (struct patchlist *) malloc (sizeof (struct patchlist));
672	*h = p;
673	p->next = NULL;
674	p->offset = dsps + 4;
675	npatches++;
676}
677
678void close_script ()
679{
680	int	i;
681
682	if (dsps == 0)
683		return;
684	if (outfp) {
685		fprintf (outfp, "const u_int32_t %s[] = {\n", script_name);
686		for (i = 0; i < dsps / 4; i += 2) {
687			fprintf (outfp, "\t0x%08x, 0x%08x", script[i],
688				script[i + 1]);
689			/* check for memory move instruction */
690			if ((script[i] & 0xe0000000) == 0xc0000000)
691				fprintf (outfp, ", 0x%08x,", script[i + 2]);
692			else
693				if ((i + 2) <= dsps / 4) fprintf (outfp, ",\t\t");
694			fprintf (outfp, "\t/* %03x - %3d */\n", i * 4, i * 4);
695			if ((script[i] & 0xe0000000) == 0xc0000000)
696				++i;
697		}
698		fprintf (outfp, "};\n\n");
699	}
700	dsps = 0;
701}
702
703void new_script (char *name)
704{
705	close_script ();
706	script_name = malloc (strlen (name) + 1);
707	strcpy (script_name, name);
708}
709
710int	reserved (char *string, int t)
711{
712	if (tokens[t].type == 0 && strcmpi (tokens[t].name, string) == 0)
713		return (1);
714	return (0);
715}
716
717int	CheckPhase (int t)
718{
719	int	i;
720
721	for (i = 0; i < 8; ++i) {
722		if (reserved (phases[i], t)) {
723			inst0 |= i << 24;
724			return (1);
725		}
726	}
727	return (0);
728}
729
730int	CheckRegister (int t)
731{
732	int	i;
733
734	if (arch <= 0) {
735		errout("'ARCH' statement missing");
736		return -1;
737	}
738	for (i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
739		if (regs[i].addr[arch - 1] >= 0 && reserved(regs[i].name, t))
740			return regs[i].addr[arch-1];
741	}
742	return (-1);
743}
744
745int	expression (int *t)
746{
747	int	value;
748	int	i = *t;
749
750	value = evaluate (i++);
751	while (i < ntokens) {
752		if (tokens[i].type == '+')
753			value += evaluate (i + 1);
754		else if (tokens[i].type == '-')
755			value -= evaluate (i + 1);
756		else
757			errout ("Unknown identifier");
758		i += 2;
759	}
760	*t = i;
761	return (value);
762}
763
764int	evaluate (t)
765{
766	int	value;
767	char	*name;
768
769	if (tokens[t].type) {
770		errout ("Expected an identifier");
771		return (0);
772	}
773	name = tokens[t].name;
774	if (*name >= '0' && *name <= '9')
775		value = number (name);
776	else
777		value = lookup (name);
778	return (value);
779}
780
781int	number (char *s)
782{
783	int	value;
784	int	n;
785	int	radix;
786
787	radix = 10;
788	if (*s == '0') {
789		++s;
790		radix = 8;
791		switch (*s) {
792		case 'x':
793		case 'X':
794			radix = 16;
795			break;
796		case 'b':
797		case 'B':
798			radix = 2;
799		}
800		if (radix != 8)
801			++s;
802	}
803	value = 0;
804	while (*s) {
805		n = *s++;
806		if (n >= '0' && n <= '9')
807			n -= '0';
808		else if (n >= 'a' && n <= 'f')
809			n -= 'a' - 10;
810		else if (n >= 'A' && n <= 'F')
811			n -= 'A' - 10;
812		else {
813			error_line();
814			fprintf (errfp, "*** Expected digit\n");
815			n = 0;
816		}
817		if (n >= radix)
818			errout ("Expected digit");
819		else
820			value = value * radix + n;
821	}
822	return (value);
823}
824
825int	lookup (char *name)
826{
827	int	i;
828	struct patchlist *p;
829
830	for (i = 0; i < nsymbols; ++i) {
831		if (strcmp (name, symbols[i].name) == 0) {
832			if ((symbols[i].flags & F_DEFINED) == 0) {
833				p = (struct patchlist *) &symbols[i].patchlist;
834				while (p->next)
835					p = p->next;
836				p->next = (struct patchlist *) malloc (sizeof (struct patchlist));
837				p = p->next;
838				p->next = NULL;
839				p->offset = dsps + 4;
840			}
841			return ((int) symbols[i].value);
842		}
843	}
844	if (nsymbols >= MAXSYMBOLS) {
845		errout ("Symbol table full");
846		return (0);
847	}
848	symbols[nsymbols].type = S_LABEL;	/* assume forward reference */
849	symbols[nsymbols].flags = 0;
850	symbols[nsymbols].value = 0;
851	p = (struct patchlist *) malloc (sizeof (struct patchlist));
852	symbols[nsymbols].patchlist = p;
853	p->next = NULL;
854	p->offset = dsps + 4;
855	symbols[nsymbols].name = malloc (strlen (name) + 1);
856	strcpy (symbols[nsymbols].name, name);
857	++nsymbols;
858	return (0);
859}
860
861void	f_arch (void)
862{
863	int i, archsave;
864
865	i = tokenix;
866
867	archsave = arch;
868	setarch(tokens[i].name);
869	if( arch == 0) {
870		errout("Unrecognized ARCH");
871		arch = archsave;
872	}
873}
874
875void	f_proc (void)
876{
877	if (tokens[tokenix].type != 0 || tokens[tokenix + 1].type != ':')
878		errout ("Invalid PROC statement");
879	else
880		new_script (tokens[tokenix].name);
881}
882
883void	f_pass (void)
884{
885	errout ("PASS option not implemented");
886}
887
888/*
889 *	f_list:  process list of symbols for the ENTRY and EXTERNAL directive
890 */
891
892void	f_list (void)
893{
894	int	i;
895	short	type;
896	short	flags;
897
898	type = strcmpi (tokens[tokenix-1].name, "ENTRY") ? S_EXTERNAL : S_LABEL;
899	flags = type == S_LABEL ? F_ENTRY : 0;
900	for (i = tokenix; i < ntokens; ++i) {
901		if (tokens[i].type != 0) {
902			errout ("Expected an identifier");
903			return;
904		}
905		define_symbol (tokens[i].name, 0, type, flags);
906		if (i + 1 < ntokens) {
907			if (tokens[++i].type == ',')
908				continue;
909			errout ("Expected a separator");
910			return;
911		}
912	}
913}
914
915/*
916 *	f_define:	process list of definitions for ABSOLUTE and RELATIVE directive
917 */
918
919void	f_define (void)
920{
921	int	i;
922	char	*name;
923	u_int32_t value;
924	int	type;
925
926	type = strcmpi (tokens[tokenix-1].name, "ABSOLUTE") ? S_RELATIVE : S_ABSOLUTE;
927	i = tokenix;
928	while (i < ntokens) {
929		if (tokens[i].type) {
930			errout ("Expected an identifier");
931			return;
932		}
933		if (tokens[i + 1].type != '=') {
934			errout ("Expected a separator");
935			return;
936		}
937		name = tokens[i].name;
938		i += 2;
939		value = expression (&i);
940		define_symbol (name, value, type, F_DEFINED);
941	}
942}
943
944void	store_inst ()
945{
946	int	i = dsps / 4;
947	int	l = 8;
948
949	if ((inst0 & 0xe0000000) == 0xc0000000)
950		l = 12;			/* Memory to memory move is 12 bytes */
951	if ((dsps + l) / 4 > MAXINST) {
952		errout ("Instruction table overflow");
953		return;
954	}
955	script[i++] = inst0;
956	script[i++] = inst1;
957	if (l == 12)
958		script[i++] = inst2;
959	if (listfp) {
960		fprintf (listfp, "\t%04x: %08x %08x", dsps, inst0, inst1);
961		if (l == 12)
962			fprintf (listfp, " %08x", inst2);
963		fprintf (listfp, "\n");
964	}
965	dsps += l;
966	inst0 = inst1 = inst2 = 0;
967	++ninsts;
968}
969
970void	f_move (void)
971{
972	if (reserved ("memory", tokenix))
973		memory_to_memory ();
974	else if (reserved ("from", tokenix) || tokens[tokenix+1].type == ',')
975		block_move ();
976	else
977		register_write ();
978	store_inst ();
979}
980
981void	f_jump (void)
982{
983	transfer (0x80000000, 0);
984}
985
986void	f_call (void)
987{
988	transfer (0x88000000, 0);
989}
990
991void	f_return (void)
992{
993	transfer (0x90000000, 1);
994}
995
996void	f_int (void)
997{
998	transfer (0x98000000, 2);
999}
1000
1001void	f_intfly (void)
1002{
1003	transfer (0x98100000, 2);
1004}
1005
1006void	f_select (void)
1007{
1008	int	t = tokenix;
1009
1010	if (reserved ("atn", t)) {
1011		inst0 = 0x01000000;
1012		++t;
1013	}
1014	select_reselect (t);
1015}
1016
1017void	f_reselect (void)
1018{
1019	select_reselect (tokenix);
1020}
1021
1022void	f_wait (void)
1023{
1024	int	i = tokenix;
1025
1026	inst1 = 0;
1027	if (reserved ("disconnect", i)) {
1028		inst0 = 0x48000000;
1029	}
1030	else {
1031		if (reserved ("reselect", i))
1032			inst0 = 0x50000000;
1033		else if (reserved ("select", i))
1034			inst0 = 0x50000000;
1035		else
1036			errout ("Expected SELECT or RESELECT");
1037		++i;
1038		if (reserved ("rel", i)) {
1039#if 0 /* driver will fix relative dsps to absolute */
1040			if (arch < ARCH710) {
1041				errout ("Wrong arch for relative dsps");
1042			}
1043#endif
1044			i += 2;
1045			inst1 = evaluate (i) - dsps - 8;
1046			inst0 |= 0x04000000;
1047		}
1048		else {
1049			inst1 = evaluate (i);
1050			patch_label();
1051		}
1052	}
1053	store_inst ();
1054}
1055
1056void	f_disconnect (void)
1057{
1058	inst0 = 0x48000000;
1059	store_inst ();
1060}
1061
1062void	f_set (void)
1063{
1064	set_clear (0x58000000);
1065}
1066
1067void	f_clear (void)
1068{
1069	set_clear (0x60000000);
1070}
1071
1072void	f_load (void)
1073{
1074	inst0 = 0xe1000000;
1075	if (arch < ARCH810) {
1076		errout ("Wrong arch for load/store");
1077		return;
1078	}
1079	loadstore(tokenix);
1080}
1081
1082void	f_store (void)
1083{
1084	int i;
1085	inst0 = 0xe0000000;
1086	if (arch < ARCH810) {
1087		errout ("Wrong arch for load/store");
1088		return;
1089	}
1090	i = tokenix;
1091	if (reserved("noflush", i)) {
1092		inst0 |= 0x2000000;
1093		i++;
1094	}
1095	loadstore(i);
1096}
1097
1098void	f_nop (void)
1099{
1100	inst0 = 0x80000000;
1101	inst1 = 0x00000000;
1102	store_inst ();
1103}
1104
1105void loadstore(int i)
1106{
1107	int reg, size;
1108
1109	reg = CheckRegister(i);
1110	if (reg < 0)
1111		errout ("Expected register");
1112	else
1113		inst0 |= reg <<  16;
1114	if (reg == 8)
1115		errout ("Register can't be SFBR");
1116	i++;
1117	if (tokens[i].type == ',')
1118		i++;
1119	else
1120		errout ("expected ','");
1121	size = evaluate(i);
1122	if (i < 1 || i > 4)
1123		errout("wrong size");
1124	if ((reg & 0x3) + size > 4)
1125		errout("size too big for register");
1126	inst0 |= size;
1127	i++;
1128	if (tokens[i].type == ',')
1129		i++;
1130	else
1131		errout ("expected ','");
1132	if (reserved("from", i) || reserved("dsarel", i)) {
1133		if (arch < ARCH710) {
1134			errout ("Wrong arch for table indirect");
1135			return;
1136		}
1137		i++;
1138		inst0 |= 0x10000000;
1139	}
1140	inst1 = evaluate(i);
1141	store_inst ();
1142}
1143
1144void	transfer (int word0, int type)
1145{
1146	int	i;
1147
1148	i = tokenix;
1149	inst0 = word0;
1150	if (type == 0 && reserved ("rel", i)) {
1151#if 0 /* driver will fix relative dsps to absolute */
1152		if (arch < ARCH710) {
1153			errout ("Wrong arch for relative dsps");
1154		}
1155#endif
1156		inst1 = evaluate (i + 2) - dsps - 8;
1157		i += 4;
1158		inst0 |= 0x00800000;
1159	}
1160	else if (type != 1) {
1161		inst1 = evaluate (i);
1162		++i;
1163		if (type == 0)
1164			patch_label();
1165	}
1166	if (i >= ntokens) {
1167		inst0 |= 0x00080000;
1168		store_inst ();
1169		return;
1170	}
1171	if (tokens[i].type != ',')
1172		errout ("Expected a separator, ',' assumed");
1173	else
1174		++i;
1175	if (reserved("when", i))
1176		inst0 |= 0x00010000;
1177	else if (reserved ("if", i) == 0) {
1178		errout ("Expected a reserved word");
1179		store_inst ();
1180		return;
1181	}
1182	i++;
1183	if (reserved("false", i)) {
1184		store_inst ();
1185		return;
1186	}
1187	if (reserved ("not", i))
1188		++i;
1189	else
1190		inst0 |= 0x00080000;
1191	if (reserved ("atn", i)) {
1192		inst0 |= 0x00020000;
1193		++i;
1194	} else if (CheckPhase (i)) {
1195		inst0 |= 0x00020000;
1196		++i;
1197	}
1198	if (i < ntokens && tokens[i].type != ',') {
1199		if (inst0 & 0x00020000) {
1200			if (inst0 & 0x00080000 && reserved ("and", i)) {
1201				++i;
1202			}
1203			else if ((inst0 & 0x00080000) == 0 && reserved ("or", i)) {
1204				++i;
1205			}
1206			else
1207				errout ("Expected a reserved word");
1208		}
1209		inst0 |= 0x00040000 + (evaluate (i++) & 0xff);
1210	}
1211	if (i < ntokens) {
1212		if (tokens[i].type == ',')
1213			++i;
1214		else
1215			errout ("Expected a separator, ',' assumed");
1216		if (reserved ("and", i) && reserved ("mask", i + 1))
1217			inst0 |= ((evaluate (i + 2) & 0xff) << 8);
1218		else
1219			errout ("Expected , AND MASK");
1220	}
1221	store_inst ();
1222}
1223
1224void 	select_reselect (int t)
1225{
1226	inst0 |= 0x40000000;		/* ATN may be set from SELECT */
1227	if (reserved ("from", t)) {
1228		if (arch < ARCH710) {
1229			errout ("Wrong arch for table indirect");
1230			return;
1231		}
1232		++t;
1233		inst0 |= 0x02000000 | evaluate (t++);
1234	}
1235	else
1236		inst0 |= (evaluate (t++) & 0xff) << 16;
1237	if (tokens[t++].type == ',') {
1238		if (reserved ("rel", t)) {
1239#if 0 /* driver will fix relative dsps to absolute */
1240			if (arch < ARCH710) {
1241				errout ("Wrong arch for relative dsps");
1242			}
1243#endif
1244			inst0 |= 0x04000000;
1245			inst1 = evaluate (t + 2) - dsps - 8;
1246		}
1247		else {
1248			inst1 = evaluate (t);
1249			patch_label();
1250		}
1251	}
1252	else
1253		errout ("Expected separator");
1254	store_inst ();
1255}
1256
1257void	set_clear (u_int32_t code)
1258{
1259	int	i = tokenix;
1260	short	need_and = 0;
1261
1262	inst0 = code;
1263	while (i < ntokens) {
1264		if (need_and) {
1265			if (reserved ("and", i))
1266				++i;
1267			else
1268				errout ("Expected AND");
1269		}
1270		if (reserved ("atn", i)) {
1271			inst0 |= 0x0008;
1272			++i;
1273		}
1274		else if (reserved ("ack", i)) {
1275			inst0 |= 0x0040;
1276			++i;
1277		}
1278		else if (reserved ("target", i)) {
1279			inst0 |= 0x0200;
1280			++i;
1281		}
1282		else if (reserved ("carry", i)) {
1283			inst0 |= 0x0400;
1284			++i;
1285		}
1286		else
1287			errout ("Expected ATN, ACK, TARGET or CARRY");
1288		need_and = 1;
1289	}
1290	store_inst ();
1291}
1292
1293void	block_move ()
1294{
1295	if (reserved ("from", tokenix)) {
1296		if (arch < ARCH710) {
1297			errout ("Wrong arch for table indirect");
1298			return;
1299		}
1300		inst1 = evaluate (tokenix+1);
1301		inst0 |= 0x10000000 | inst1;	/*** ??? to match Zeus script */
1302		tokenix += 2;
1303	}
1304	else {
1305		inst0 |= evaluate (tokenix++);	/* count */
1306		tokenix++;			/* skip ',' */
1307		if (reserved ("ptr", tokenix)) {
1308			++tokenix;
1309			inst0 |= 0x20000000;
1310		}
1311		inst1 = evaluate (tokenix++);	/* address */
1312	}
1313	if (tokens[tokenix].type != ',')
1314		errout ("Expected separator");
1315	if (reserved ("when", tokenix + 1)) {
1316		inst0 |= 0x08000000;
1317		CheckPhase (tokenix + 2);
1318	}
1319	else if (reserved ("with", tokenix + 1)) {
1320		CheckPhase (tokenix + 2);
1321	}
1322	else
1323		errout ("Expected WITH or WHEN");
1324}
1325
1326void	register_write ()
1327{
1328	/*
1329	 * MOVE reg/data8 TO reg			register write
1330	 * MOVE reg <op> data8 TO reg			register write
1331	 * MOVE reg + data8 TO reg WITH CARRY		register write
1332	 */
1333	int	op;
1334	int	reg;
1335	int	data;
1336
1337	if (reserved ("to", tokenix+1))
1338		op = 0;
1339	else if (reserved ("shl", tokenix+1))
1340		op = 1;
1341	else if (reserved ("shr", tokenix+1))
1342		op = 5;
1343	else if (tokens[tokenix+1].type == '|')
1344		op = 2;
1345	else if (reserved ("xor", tokenix+1))
1346		op = 3;
1347	else if (tokens[tokenix+1].type == '&')
1348		op = 4;
1349	else if (tokens[tokenix+1].type == '+')
1350		op = 6;
1351	else if (tokens[tokenix+1].type == '-')
1352		op = 8;
1353	else
1354		errout ("Unknown register operator");
1355	switch (op) {
1356	case 2:
1357	case 3:
1358	case 4:
1359	case 6:
1360	case 8:
1361		if (reserved ("to", tokenix+3) == 0)
1362			errout ("Register command expected TO");
1363	}
1364	reg = CheckRegister (tokenix);
1365	if (reg < 0) {			/* Not register, must be data */
1366		data = evaluate (tokenix);
1367		if (op)
1368			errout ("Register operator not move");
1369		reg = CheckRegister (tokenix+2);
1370		if (reg < 0)
1371			errout ("Expected register");
1372		inst0 = 0x78000000 | (data << 8) | reg << 16;
1373#if 0
1374fprintf (listfp, "Move data to register: %02x %d\n", data, reg);
1375#endif
1376	} else if (op) {
1377		switch (op) {
1378		case 2:
1379		case 3:
1380		case 4:
1381		case 6:
1382		case 8:
1383			inst0 = 0;
1384			/* A register read/write operator */
1385			if (reserved("sfbr", tokenix+2)) {
1386				if (arch < ARCH825)
1387					errout("wrong arch for add with SFBR");
1388				if (op == 8)
1389					errout("can't substract SFBR");
1390				inst0 |= 0x00800000;
1391				data = 0;
1392			} else
1393				data = evaluate (tokenix+2);
1394			if (tokenix+5 < ntokens) {
1395				if (!reserved("with", tokenix+5) ||
1396				    !reserved("carry", tokenix+6)) {
1397					errout("Expected 'WITH CARRY'");
1398				} else if (op != 6) {
1399					errout("'WITH CARRY' only valide "
1400					    "with '+'");
1401				}
1402				op = 7;
1403			}
1404			if (op == 8) {
1405				data = -data;
1406				op = 6;
1407			}
1408			inst0 |= (data & 0xff) << 8;
1409			data = CheckRegister (tokenix+4);
1410			break;
1411		default:
1412			data = CheckRegister (tokenix+2);
1413			break;
1414		}
1415		if (data < 0)
1416			errout ("Expected register");
1417		if (reg != data && reg != 8 && data != 8)
1418			errout ("One register MUST be SBFR");
1419		if (reg == data) {	/* A register read/modify/write */
1420#if 0
1421fprintf (listfp, "Read/modify register: %02x %d %d\n", inst0 >> 8, op, reg);
1422#endif
1423			inst0 |= 0x78000000 | (op << 24) | (reg << 16);
1424		}
1425		else {			/* A move to/from SFBR */
1426			if (reg == 8) {	/* MOVE SFBR <> TO reg */
1427#if 0
1428fprintf (listfp, "Move SFBR to register: %02x %d %d\n", inst0 >> 8, op, data);
1429#endif
1430				inst0 |= 0x68000000 | (op << 24) | (data << 16);
1431			}
1432			else {
1433#if 0
1434fprintf (listfp, "Move register to SFBR: %02x %d %d\n", inst0 >> 8, op, reg);
1435#endif
1436				inst0 |= 0x70000000 | (op << 24) | (reg << 16);
1437			}
1438		}
1439	} else {				/* register to register */
1440		data = CheckRegister (tokenix+2);
1441		if (data < 0)
1442			errout ("Expected register");
1443		if (reg == 8)		/* move SFBR to reg */
1444			inst0 = 0x6a000000 | (data << 16);
1445		else if (data == 8)	/* move reg to SFBR */
1446			inst0 = 0x72000000 | (reg << 16);
1447		else
1448			errout ("One register must be SFBR");
1449	}
1450}
1451
1452void	memory_to_memory ()
1453{
1454	inst0 = 0xc0000000 + evaluate (tokenix+1);
1455	inst1 = evaluate (tokenix+3);
1456	/*
1457	 * need to hack dsps, otherwise patch offset will be wrong for
1458	 * second pointer
1459	 */
1460	dsps += 4;
1461	inst2 = evaluate (tokenix+5);
1462	dsps -= 4;
1463}
1464
1465void	error_line()
1466{
1467	if (errfp != listfp && errfp && err_listed == 0) {
1468		fprintf (errfp, "%3d:  %s", lineno, inbuf);
1469		err_listed = 1;
1470	}
1471}
1472
1473char *	makefn (base, sub)
1474	char *base;
1475	char *sub;
1476{
1477	char *fn;
1478
1479	fn = malloc (strlen (base) + strlen (sub) + 2);
1480	strcpy (fn, base);
1481	base = strrchr(fn, '.');
1482	if (base)
1483		*base = 0;
1484	strcat (fn, ".");
1485	strcat (fn, sub);
1486	return (fn);
1487}
1488
1489void	usage()
1490{
1491	fprintf (stderr, "usage: scc sourcfile [options]\n");
1492	exit(1);
1493}
1494