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