ncr53cxxx.c revision 1.2 1 /* $NetBSD: ncr53cxxx.c,v 1.2 2000/04/25 16:01:16 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.2 2000/04/25 16:01:16 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].type == S_ABSOLUTE)
496 code = "A_";
497 else if (symbols[i].type == S_RELATIVE)
498 code = "R_";
499 else if (symbols[i].type == S_EXTERNAL)
500 code = "E_";
501 else if (symbols[i].flags & F_ENTRY)
502 code = "Ent_";
503 else
504 continue;
505 fprintf (outfp, "#define\t%s%s\t0x%08x\n", code, symbols[i].name,
506 symbols[i].value);
507 if (symbols[i].flags & F_ENTRY || symbols[i].patchlist == NULL)
508 continue;
509 fprintf (outfp, "u_int32_t %s%s_Used[] = {\n", code, symbols[i].name);
510 #if 1
511 p = symbols[i].patchlist;
512 while (p) {
513 fprintf (outfp, "\t0x%08x,\n", p->offset / 4);
514 p = p->next;
515 }
516 #endif
517 fprintf (outfp, "};\n\n");
518 }
519 /* patches ? */
520 }
521
522 void list_symbols ()
523 {
524 int i;
525
526 if (nsymbols == 0 || listfp == NULL)
527 return;
528 fprintf (listfp, "\n\nValue Type Symbol\n");
529 for (i = 0; i < nsymbols; ++i) {
530 fprintf (listfp, "%08x: %-8s %s\n", symbols[i].value,
531 stypes[symbols[i].type], symbols[i].name);
532 }
533 }
534
535 void errout (char *text)
536 {
537 error_line();
538 fprintf (errfp, "*** %s ***\n", text);
539 }
540
541 void parse ()
542 {
543 char *p = inbuf;
544 char c;
545 char string[64];
546 char *s;
547
548 ntokens = tokenix = 0;
549 while (1) {
550 while ((c = *p++) && c != '\n' && (c <= ' ' || c == '\t'))
551 ;
552 if (c == '\n' || c == 0 || c == ';')
553 break;
554 if (ntokens >= MAXTOKENS) {
555 errout ("Token table full");
556 break;
557 }
558 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
559 (c >= 'A' && c <= 'Z') || c == '$' || c == '_') {
560 s = string;
561 *s++ = c;
562 while (((c = *p) >= '0' && c <= '9') ||
563 (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
564 c == '_' || c == '$') {
565 *s++ = *p++;
566 }
567 *s = 0;
568 tokens[ntokens].name = malloc (strlen (string) + 1);
569 strcpy (tokens[ntokens].name, string);
570 tokens[ntokens].type = 0;
571 }
572 else {
573 tokens[ntokens].type = c;
574 }
575 ++ntokens;
576 }
577 return;
578 }
579
580 void process ()
581 {
582 int i;
583
584 if (tokens[tokenix].type) {
585 error_line();
586 fprintf (errfp, "Error: expected directive, found '%c'\n",
587 tokens[tokenix].type);
588 return;
589 }
590 for (i = 0; directives[i].name; ++i) {
591 if (strcmpi (directives[i].name, tokens[tokenix].name) == 0)
592 break;
593 }
594 if (directives[i].name == NULL) {
595 error_line();
596 fprintf (errfp, "Error: expected directive, found \"%s\"\n",
597 tokens[tokenix].name);
598 return;
599 }
600 if (directives[i].func == NULL) {
601 error_line();
602 fprintf (errfp, "No function for directive \"%s\"\n", tokens[tokenix].name);
603 } else {
604 #if 0
605 fprintf (listfp, "Processing directive \"%s\"\n", directives[i].name);
606 #endif
607 ++tokenix;
608 (*directives[i].func) ();
609 }
610 }
611
612 void define_symbol (char *name, u_int32_t value, short type, short flags)
613 {
614 int i;
615 struct patchlist *p;
616
617 for (i = 0; i < nsymbols; ++i) {
618 if (symbols[i].type == type && strcmp (symbols[i].name, name) == 0) {
619 if (symbols[i].flags & F_DEFINED) {
620 error_line();
621 fprintf (errfp, "*** Symbol \"%s\" multiply defined\n",
622 name);
623 } else {
624 symbols[i].flags |= flags;
625 symbols[i].value = value;
626 p = symbols[i].patchlist;
627 while (p) {
628 if (p->offset > dsps)
629 errout ("Whoops\007");
630 else
631 script[p->offset / 4] = dsps - p->offset - 4;
632 p = p->next;
633 }
634 }
635 return;
636 }
637 }
638 if (nsymbols >= MAXSYMBOLS) {
639 errout ("Symbol table full");
640 return;
641 }
642 symbols[nsymbols].type = type;
643 symbols[nsymbols].flags = flags;
644 symbols[nsymbols].value = value;
645 symbols[nsymbols].patchlist = NULL;
646 symbols[nsymbols].name = malloc (strlen (name) + 1);
647 strcpy (symbols[nsymbols].name, name);
648 ++nsymbols;
649 }
650
651 void close_script ()
652 {
653 int i;
654
655 if (dsps == 0)
656 return;
657 if (outfp) {
658 fprintf (outfp, "const u_int32_t %s[] = {\n", script_name);
659 for (i = 0; i < dsps / 4; i += 2) {
660 fprintf (outfp, "\t0x%08x, 0x%08x", script[i],
661 script[i + 1]);
662 /* check for memory move instruction */
663 if ((script[i] & 0xe0000000) == 0xc0000000)
664 fprintf (outfp, ", 0x%08x,", script[i + 2]);
665 else
666 if ((i + 2) <= dsps / 4) fprintf (outfp, ",\t\t");
667 fprintf (outfp, "\t/* %03x - %3d */\n", i * 4, i * 4);
668 if ((script[i] & 0xe0000000) == 0xc0000000)
669 ++i;
670 }
671 fprintf (outfp, "};\n\n");
672 }
673 dsps = 0;
674 }
675
676 void new_script (char *name)
677 {
678 close_script ();
679 script_name = malloc (strlen (name) + 1);
680 strcpy (script_name, name);
681 }
682
683 int reserved (char *string, int t)
684 {
685 if (tokens[t].type == 0 && strcmpi (tokens[t].name, string) == 0)
686 return (1);
687 return (0);
688 }
689
690 int CheckPhase (int t)
691 {
692 int i;
693
694 for (i = 0; i < 8; ++i) {
695 if (reserved (phases[i], t)) {
696 inst0 |= i << 24;
697 return (1);
698 }
699 }
700 return (0);
701 }
702
703 int CheckRegister (int t)
704 {
705 int i;
706
707 if (arch <= 0) {
708 errout("'ARCH' statement missing");
709 return -1;
710 }
711 for (i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
712 if (regs[i].addr[arch - 1] >= 0 && reserved(regs[i].name, t))
713 return regs[i].addr[arch-1];
714 }
715 return (-1);
716 }
717
718 int expression (int *t)
719 {
720 int value;
721 int i = *t;
722
723 value = evaluate (i++);
724 while (i < ntokens) {
725 if (tokens[i].type == '+')
726 value += evaluate (i + 1);
727 else if (tokens[i].type == '-')
728 value -= evaluate (i + 1);
729 else
730 errout ("Unknown identifier");
731 i += 2;
732 }
733 *t = i;
734 return (value);
735 }
736
737 int evaluate (t)
738 {
739 int value;
740 char *name;
741
742 if (tokens[t].type) {
743 errout ("Expected an identifier");
744 return (0);
745 }
746 name = tokens[t].name;
747 if (*name >= '0' && *name <= '9')
748 value = number (name);
749 else
750 value = lookup (name);
751 return (value);
752 }
753
754 int number (char *s)
755 {
756 int value;
757 int n;
758 int radix;
759
760 radix = 10;
761 if (*s == '0') {
762 ++s;
763 radix = 8;
764 switch (*s) {
765 case 'x':
766 case 'X':
767 radix = 16;
768 break;
769 case 'b':
770 case 'B':
771 radix = 2;
772 }
773 if (radix != 8)
774 ++s;
775 }
776 value = 0;
777 while (*s) {
778 n = *s++;
779 if (n >= '0' && n <= '9')
780 n -= '0';
781 else if (n >= 'a' && n <= 'f')
782 n -= 'a' - 10;
783 else if (n >= 'A' && n <= 'F')
784 n -= 'A' - 10;
785 else {
786 error_line();
787 fprintf (errfp, "*** Expected digit\n");
788 n = 0;
789 }
790 if (n >= radix)
791 errout ("Expected digit");
792 else
793 value = value * radix + n;
794 }
795 return (value);
796 }
797
798 int lookup (char *name)
799 {
800 int i;
801 struct patchlist *p;
802
803 for (i = 0; i < nsymbols; ++i) {
804 if (strcmp (name, symbols[i].name) == 0) {
805 if ((symbols[i].flags & F_DEFINED) == 0) {
806 p = (struct patchlist *) &symbols[i].patchlist;
807 while (p->next)
808 p = p->next;
809 p->next = (struct patchlist *) malloc (sizeof (struct patchlist));
810 p = p->next;
811 p->next = NULL;
812 p->offset = dsps + 4;
813 }
814 return ((int) symbols[i].value);
815 }
816 }
817 if (nsymbols >= MAXSYMBOLS) {
818 errout ("Symbol table full");
819 return (0);
820 }
821 symbols[nsymbols].type = S_LABEL; /* assume forward reference */
822 symbols[nsymbols].flags = 0;
823 symbols[nsymbols].value = 0;
824 p = (struct patchlist *) malloc (sizeof (struct patchlist));
825 symbols[nsymbols].patchlist = p;
826 p->next = NULL;
827 p->offset = dsps + 4;
828 symbols[nsymbols].name = malloc (strlen (name) + 1);
829 strcpy (symbols[nsymbols].name, name);
830 ++nsymbols;
831 return (0);
832 }
833
834 void f_arch (void)
835 {
836 int i, archsave;
837
838 i = tokenix;
839
840 archsave = arch;
841 setarch(tokens[i].name);
842 if( arch == 0) {
843 errout("Unrecognized ARCH");
844 arch = archsave;
845 }
846 }
847
848 void f_proc (void)
849 {
850 if (tokens[tokenix].type != 0 || tokens[tokenix + 1].type != ':')
851 errout ("Invalid PROC statement");
852 else
853 new_script (tokens[tokenix].name);
854 }
855
856 void f_pass (void)
857 {
858 errout ("PASS option not implemented");
859 }
860
861 /*
862 * f_list: process list of symbols for the ENTRY and EXTERNAL directive
863 */
864
865 void f_list (void)
866 {
867 int i;
868 short type;
869 short flags;
870
871 type = strcmpi (tokens[tokenix-1].name, "ENTRY") ? S_EXTERNAL : S_LABEL;
872 flags = type == S_LABEL ? F_ENTRY : 0;
873 for (i = tokenix; i < ntokens; ++i) {
874 if (tokens[i].type != 0) {
875 errout ("Expected an identifier");
876 return;
877 }
878 define_symbol (tokens[i].name, 0, type, flags);
879 if (i + 1 < ntokens) {
880 if (tokens[++i].type == ',')
881 continue;
882 errout ("Expected a separator");
883 return;
884 }
885 }
886 }
887
888 /*
889 * f_define: process list of definitions for ABSOLUTE and RELATIVE directive
890 */
891
892 void f_define (void)
893 {
894 int i;
895 char *name;
896 u_int32_t value;
897 int type;
898
899 type = strcmpi (tokens[tokenix-1].name, "ABSOLUTE") ? S_RELATIVE : S_ABSOLUTE;
900 i = tokenix;
901 while (i < ntokens) {
902 if (tokens[i].type) {
903 errout ("Expected an identifier");
904 return;
905 }
906 if (tokens[i + 1].type != '=') {
907 errout ("Expected a separator");
908 return;
909 }
910 name = tokens[i].name;
911 i += 2;
912 value = expression (&i);
913 define_symbol (name, value, type, F_DEFINED);
914 }
915 }
916
917 void store_inst ()
918 {
919 int i = dsps / 4;
920 int l = 8;
921
922 if ((inst0 & 0xe0000000) == 0xc0000000)
923 l = 12; /* Memory to memory move is 12 bytes */
924 if ((dsps + l) / 4 > MAXINST) {
925 errout ("Instruction table overflow");
926 return;
927 }
928 script[i++] = inst0;
929 script[i++] = inst1;
930 if (l == 12)
931 script[i++] = inst2;
932 if (listfp) {
933 fprintf (listfp, "\t%04x: %08x %08x", dsps, inst0, inst1);
934 if (l == 12)
935 fprintf (listfp, " %08x", inst2);
936 fprintf (listfp, "\n");
937 }
938 dsps += l;
939 inst0 = inst1 = inst2 = 0;
940 ++ninsts;
941 }
942
943 void f_move (void)
944 {
945 if (reserved ("memory", tokenix))
946 memory_to_memory ();
947 else if (reserved ("from", tokenix) || tokens[tokenix+1].type == ',')
948 block_move ();
949 else
950 register_write ();
951 store_inst ();
952 }
953
954 void f_jump (void)
955 {
956 transfer (0x80000000, 0);
957 }
958
959 void f_call (void)
960 {
961 transfer (0x88000000, 0);
962 }
963
964 void f_return (void)
965 {
966 transfer (0x90000000, 1);
967 }
968
969 void f_int (void)
970 {
971 transfer (0x98000000, 2);
972 }
973
974 void f_select (void)
975 {
976 int t = tokenix;
977
978 if (reserved ("atn", t)) {
979 inst0 = 0x01000000;
980 ++t;
981 }
982 select_reselect (t);
983 }
984
985 void f_reselect (void)
986 {
987 select_reselect (tokenix);
988 }
989
990 void f_wait (void)
991 {
992 int i = tokenix;
993
994 inst1 = 0;
995 if (reserved ("disconnect", i)) {
996 inst0 = 0x48000000;
997 }
998 else {
999 if (reserved ("reselect", i))
1000 inst0 = 0x50000000;
1001 else if (reserved ("select", i))
1002 inst0 = 0x50000000;
1003 else
1004 errout ("Expected SELECT or RESELECT");
1005 ++i;
1006 if (reserved ("rel", i)) {
1007 i += 2;
1008 inst1 = evaluate (i) - dsps - 8;
1009 inst0 |= 0x04000000;
1010 }
1011 else
1012 inst1 = evaluate (i);
1013 }
1014 store_inst ();
1015 }
1016
1017 void f_disconnect (void)
1018 {
1019 inst0 = 0x48000000;
1020 store_inst ();
1021 }
1022
1023 void f_set (void)
1024 {
1025 set_clear (0x58000000);
1026 }
1027
1028 void f_clear (void)
1029 {
1030 set_clear (0x60000000);
1031 }
1032
1033 void f_load (void)
1034 {
1035 inst0 = 0xe1000000;
1036 if (arch < ARCH810) {
1037 errout ("Wrong arch for load/store");
1038 return;
1039 }
1040 loadstore(tokenix);
1041 }
1042
1043 void f_store (void)
1044 {
1045 int i;
1046 inst0 = 0xe0000000;
1047 if (arch < ARCH810) {
1048 errout ("Wrong arch for load/store");
1049 return;
1050 }
1051 i = tokenix;
1052 if (reserved("noflush", i)) {
1053 inst0 |= 0x2000000;
1054 i++;
1055 }
1056 loadstore(i);
1057 }
1058
1059 void f_nop (void)
1060 {
1061 inst0 = 0x10000000;
1062 inst1 = 0x00000000;
1063 store_inst ();
1064 }
1065
1066 void loadstore(int i)
1067 {
1068 int reg, size;
1069
1070 reg = CheckRegister(i);
1071 if (reg < 0)
1072 errout ("Expected register");
1073 else
1074 inst0 |= reg << 16;
1075 if (reg == 8)
1076 errout ("Register can't be SFBR");
1077 i++;
1078 if (tokens[i].type == ',')
1079 i++;
1080 else
1081 errout ("expected ','");
1082 size = evaluate(i);
1083 if (i < 1 || i > 4)
1084 errout("wrong size");
1085 if ((reg & 0x3) + size > 4)
1086 errout("size too big for register");
1087 inst0 |= size;
1088 i++;
1089 if (tokens[i].type == ',')
1090 i++;
1091 else
1092 errout ("expected ','");
1093 if (reserved("from", i) || reserved("dsarel", i)) {
1094 i++;
1095 inst0 |= 0x10000000;
1096 }
1097 inst1 = evaluate(i);
1098 store_inst ();
1099 }
1100
1101 void transfer (int word0, int type)
1102 {
1103 int i;
1104
1105 i = tokenix;
1106 inst0 = word0;
1107 if (type == 0 && reserved ("rel", i)) {
1108 inst1 = evaluate (i + 2) - dsps - 8;
1109 i += 3;
1110 inst0 |= 0x00800000;
1111 }
1112 else if (type != 1) {
1113 inst1 = evaluate (i);
1114 }
1115 ++i;
1116 if (i >= ntokens) {
1117 inst0 |= 0x00080000;
1118 store_inst ();
1119 return;
1120 }
1121 if (tokens[i].type != ',')
1122 errout ("Expected a separator, ',' assumed");
1123 else
1124 ++i;
1125 if (reserved("when", i))
1126 inst0 |= 0x00010000;
1127 else if (reserved ("if", i) == 0) {
1128 errout ("Expected a reserved word");
1129 store_inst ();
1130 return;
1131 }
1132 if (reserved ("not", ++i))
1133 ++i;
1134 else
1135 inst0 |= 0x00080000;
1136 if (reserved ("atn", i)) {
1137 inst0 |= 0x00020000;
1138 ++i;
1139 } else if (CheckPhase (i)) {
1140 inst0 |= 0x00020000;
1141 ++i;
1142 }
1143 if (i < ntokens && tokens[i].type != ',') {
1144 if (inst0 & 0x00020000) {
1145 if (inst0 & 0x00080000 && reserved ("and", i)) {
1146 ++i;
1147 }
1148 else if ((inst0 & 0x00080000) == 0 && reserved ("or", i)) {
1149 ++i;
1150 }
1151 else
1152 errout ("Expected a reserved word");
1153 }
1154 inst0 |= 0x00040000 + (evaluate (i++) & 0xff);
1155 }
1156 if (i < ntokens) {
1157 if (tokens[i].type == ',')
1158 ++i;
1159 else
1160 errout ("Expected a separator, ',' assumed");
1161 if (reserved ("and", i) && reserved ("mask", i + 1))
1162 inst0 |= ((evaluate (i + 2) & 0xff) << 8);
1163 else
1164 errout ("Expected , AND MASK");
1165 }
1166 store_inst ();
1167 }
1168
1169 void select_reselect (int t)
1170 {
1171 inst0 |= 0x40000000; /* ATN may be set from SELECT */
1172 if (reserved ("from", t)) {
1173 ++t;
1174 inst0 |= 0x02000000 | evaluate (t++);
1175 }
1176 else
1177 inst0 |= (evaluate (t++) & 0xff) << 16;
1178 if (tokens[t++].type == ',') {
1179 if (reserved ("rel", t)) {
1180 inst0 |= 0x04000000;
1181 inst1 = evaluate (t + 2) - dsps - 8;
1182 }
1183 else
1184 inst1 = evaluate (t);
1185 }
1186 else
1187 errout ("Expected separator");
1188 store_inst ();
1189 }
1190
1191 void set_clear (u_int32_t code)
1192 {
1193 int i = tokenix;
1194 short need_and = 0;
1195
1196 inst0 = code;
1197 while (i < ntokens) {
1198 if (need_and) {
1199 if (reserved ("and", i))
1200 ++i;
1201 else
1202 errout ("Expected AND");
1203 }
1204 if (reserved ("atn", i)) {
1205 inst0 |= 0x0008;
1206 ++i;
1207 }
1208 else if (reserved ("ack", i)) {
1209 inst0 |= 0x0040;
1210 ++i;
1211 }
1212 else if (reserved ("target", i)) {
1213 inst0 |= 0x0200;
1214 ++i;
1215 }
1216 else
1217 errout ("Expected ATN, ACK, or TARGET");
1218 need_and = 1;
1219 }
1220 store_inst ();
1221 }
1222
1223 void block_move ()
1224 {
1225 if (reserved ("from", tokenix)) {
1226 inst1 = evaluate (tokenix+1);
1227 inst0 |= 0x10000000 | inst1; /*** ??? to match Zeus script */
1228 tokenix += 2;
1229 }
1230 else {
1231 inst0 |= evaluate (tokenix++); /* count */
1232 tokenix++; /* skip ',' */
1233 if (reserved ("ptr", tokenix)) {
1234 ++ tokenix;
1235 inst0 |= 0x20000000;
1236 }
1237 inst1 = evaluate (tokenix++); /* address */
1238 }
1239 if (tokens[tokenix].type != ',')
1240 errout ("Expected separator");
1241 if (reserved ("when", tokenix + 1)) {
1242 inst0 |= 0x08000000;
1243 CheckPhase (tokenix + 2);
1244 }
1245 else if (reserved ("with", tokenix + 1)) {
1246 CheckPhase (tokenix + 2);
1247 }
1248 else
1249 errout ("Expected WITH or WHEN");
1250 }
1251
1252 void register_write ()
1253 {
1254 /*
1255 * MOVE reg/data8 TO reg register write
1256 * MOVE reg <op> data8 TO reg register write
1257 * MOVE reg + data8 TO reg WITH CARRY register write
1258 */
1259 int op;
1260 int reg;
1261 int data;
1262
1263 if (reserved ("to", tokenix+1))
1264 op = 0;
1265 else if (tokens[tokenix+1].type == '|')
1266 op = 2;
1267 else if (tokens[tokenix+1].type == '&')
1268 op = 4;
1269 else if (tokens[tokenix+1].type == '+')
1270 op = 6;
1271 else if (tokens[tokenix+1].type == '-')
1272 op = 8;
1273 else
1274 errout ("Unknown register operator");
1275 if (op && reserved ("to", tokenix+3) == 0)
1276 errout ("Register command expected TO");
1277 reg = CheckRegister (tokenix);
1278 if (reg < 0) { /* Not register, must be data */
1279 data = evaluate (tokenix);
1280 if (op)
1281 errout ("Register operator not move");
1282 reg = CheckRegister (tokenix+2);
1283 if (reg < 0)
1284 errout ("Expected register");
1285 inst0 = 0x78000000 | (data << 8) | reg << 16;
1286 #if 0
1287 fprintf (listfp, "Move data to register: %02x %d\n", data, reg);
1288 #endif
1289 }
1290 else if (op) { /* A register read/write operator */
1291 data = evaluate (tokenix+2);
1292 if (tokenix+5 < ntokens) {
1293 if (!reserved("with", tokenix+5) ||
1294 !reserved("carry", tokenix+6)) {
1295 errout("Expected 'WITH CARRY'");
1296 } else if (op != 6) {
1297 errout("'WITH CARRY' only valide with '+'");
1298 }
1299 op = 7;
1300 }
1301 if (op == 8) {
1302 data = -data;
1303 op = 6;
1304 }
1305 inst0 = (data & 0xff) << 8;
1306 data = CheckRegister (tokenix+4);
1307 if (data < 0)
1308 errout ("Expected register");
1309 if (reg != data && reg != 8 && data != 8)
1310 errout ("One register MUST be SBFR");
1311 if (reg == data) { /* A register read/modify/write */
1312 #if 0
1313 fprintf (listfp, "Read/modify register: %02x %d %d\n", inst0 >> 8, op, reg);
1314 #endif
1315 inst0 |= 0x78000000 | (op << 24) | (reg << 16);
1316 }
1317 else { /* A move to/from SFBR */
1318 if (reg == 8) { /* MOVE SFBR <> TO reg */
1319 #if 0
1320 fprintf (listfp, "Move SFBR to register: %02x %d %d\n", inst0 >> 8, op, data);
1321 #endif
1322 inst0 |= 0x68000000 | (op << 24) | (data << 16);
1323 }
1324 else {
1325 #if 0
1326 fprintf (listfp, "Move register to SFBR: %02x %d %d\n", inst0 >> 8, op, reg);
1327 #endif
1328 inst0 |= 0x70000000 | (op << 24) | (reg << 16);
1329 }
1330 }
1331 }
1332 else { /* register to register */
1333 data = CheckRegister (tokenix+2);
1334 if (reg == 8) /* move SFBR to reg */
1335 inst0 = 0x6a000000 | (data << 16);
1336 else if (data == 8) /* move reg to SFBR */
1337 inst0 = 0x72000000 | (reg << 16);
1338 else
1339 errout ("One register must be SFBR");
1340 }
1341 }
1342
1343 void memory_to_memory ()
1344 {
1345 inst0 = 0xc0000000 + evaluate (tokenix+1);
1346 inst1 = evaluate (tokenix+3);
1347 /*
1348 * need to hack dsps, otherwise patch offset will be wrong for
1349 * second pointer
1350 */
1351 dsps += 4;
1352 inst2 = evaluate (tokenix+5);
1353 dsps -= 4;
1354 }
1355
1356 void error_line()
1357 {
1358 if (errfp != listfp && errfp && err_listed == 0) {
1359 fprintf (errfp, "%3d: %s", lineno, inbuf);
1360 err_listed = 1;
1361 }
1362 }
1363
1364 char * makefn (base, sub)
1365 char *base;
1366 char *sub;
1367 {
1368 char *fn;
1369
1370 fn = malloc (strlen (base) + strlen (sub) + 2);
1371 strcpy (fn, base);
1372 base = strrchr(fn, '.');
1373 if (base)
1374 *base = 0;
1375 strcat (fn, ".");
1376 strcat (fn, sub);
1377 return (fn);
1378 }
1379
1380 void usage()
1381 {
1382 fprintf (stderr, "usage: scc sourcfile [options]\n");
1383 exit(1);
1384 }
1385