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