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