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