xref: /plan9/sys/src/cmd/aux/na/na.y (revision 19dd451459a1979c0849454f4d98874fa41fae59)
1 /* NCR53c8xx assembler */
2 %{
3 #include <u.h>
4 #include <libc.h>
5 #include <stdio.h>
6 #include <ctype.h>
7 
8 #include "na.h"
9 
10 #define COND_WAIT (1L << 16)
11 #define COND_TRUE (1L << 19)
12 #define COND_INTFLY (1L << 20)
13 #define COND_CARRY (1L << 21)
14 #define COND_REL (1L << 23)
15 #define COND_PHASE (1L << 17)
16 #define COND_DATA (1L << 18)
17 
18 #define IO_REL (1L << 26)
19 
20 #define MOVE_MODE (1L << 27)
21 
22 int yylex(void);
23 int yyparse(void);
24 void assemble(void);
25 void yyerror(char *, ...);
26 void yywarn(char *, ...);
27 void p2error(int line, char *);
28 
29 struct addr {
30 	int type; /* 0 - direct, 1 - indirect 2 - table indirect */
31 	unsigned long offset;
32 };
33 
34 typedef enum Type { Const, Addr, Table, Extern, Reg, Unknown, Error } Type;
35 
36 struct sym {
37 	char *name;
38 	int set;
39 	Type t;
40 	long value;
41 	struct sym *next;
42 };
43 
44 struct sym *findsym(char *name);
45 struct sym *symlist;
46 
47 void newsym(struct sym *s, Type t, long v);
48 
49 struct binary {
50 	char len;
51 	unsigned long data[3];
52 	unsigned char patch[3];
53 };
54 
55 #define MAXCPPOPTS 30
56 #define MAX_PATCHES 1000
57 struct na_patch patch[MAX_PATCHES];
58 int patches;
59 
60 struct binary out;
61 
62 struct expval {
63 	Type t;
64 	long value;
65 };
66 
67 struct expval eval(struct expval a, struct expval b, char op);
68 
69 int patchtype(Type t);
70 void fixup(void);
71 
72 unsigned dot;
73 unsigned externs;
74 int errors, warnings;
75 struct sym *externp[100];
76 
77 void regmove(unsigned char src_reg, unsigned char op,
78     unsigned char dst_reg, struct expval *imm);
79 
80 void preprocess(char *in, FILE *out);
81 
82 int mk24bitssigned(long *l);
83 long mkreladdr(long value, int len);
84 long chkreladdr(int d, struct expval *e, int len, long relrv);
85 int pass2;
86 FILE *in_f;
87 
88 int yyline = 0;
89 char yyfilename[200];
90 char line[500];
91 char *cppopts[MAXCPPOPTS];
92 int ncppopts;
93 int wflag;
94 %}
95 
96 %union {
97 	long n;
98 	struct sym *s;
99 	struct expval e;
100 }
101 
102 %token NUM MOVE WHEN SYMBOL SELECT WAIT DISCONNECT RESELECT SET CLEAR
103 %token DATA_OUT DATA_IN COMMAND STATUS RESERVED_OUT RESERVED_IN MESSAGE_OUT
104 %token MESSAGE_IN WITH ATN FAIL CARRY TARGET ACK COMMENT TO
105 %token SCNTL0 SCNTL1 SCNTL2 SCNTL3 SCID SXFER SDID GPREG
106 %token SFBR SOCL SSID SBCL DSTAT SSTAT0 SSTAT1 SSTAT2
107 %token ISTAT CTEST0 CTEST1 CTEST2 CTEST3 TEMP DFIFO CTEST4 CTEST5 CTEST6
108 %token DBC DCMD DNAD DSP DSPS DMODE DIEN DWT DCNTL ADDER
109 %token SIEN0 SIEN1 SIST0 SIST1 SLPAR MACNTL GPCNTL STIME0 STIME1 RESPID
110 %token STEST0 STEST1 STEST2 STEST3 SIDL SODL SBDL
111 %token SHL SHR AND OR XOR ADD ADDC
112 %token JUMP CALL RETURN INT INTFLY NOT ABSOLUTE MASK IF REL PTR
113 %token TABLE FROM MEMORY NOP EXTERN
114 %token SCRATCHA0 SCRATCHA1 SCRATCHA2 SCRATCHA3
115 %token SCRATCHB0 SCRATCHB1 SCRATCHB2 SCRATCHB3
116 %token SCRATCHC0 SCRATCHC1 SCRATCHC2 SCRATCHC3
117 %token DSA0 DSA1 DSA2 DSA3
118 %token DEFW
119 
120 %left '-' '+'
121 %left '*' '/'
122 %left NEG     /* negation--unary minus */
123 %right '^'    /* exponentiation        */
124 %type <n> NUM phase .atn set_list set_bit regA reg
125 %type <n> set_cmd .cond condsfbr condphase
126 %type <n> jump_or_call .ptr
127 %type <s> SYMBOL
128 %type <e> exp byteexp regexp
129 
130 /* Grammar follows */
131 %%
132 input:    /* empty string */
133         | input line
134 ;
135 
136 line:	.label .opcode .comment '\n'
137 	{
138 		if (pass2) {
139 			int x;
140 			for (x = 0; x < out.len; x++) {
141 				printf("/* %.4x */ 0x%.8lxL,",
142 				    dot, out.data[x]);
143 				if (x == 0) {
144 					printf(" /*\t");
145 					fwrite(line,
146 					    strlen(line) - 1, 1, stdout);
147 					printf(" */");
148 				}
149 				printf("\n");
150 				if (out.patch[x]) {
151 					patch[patches].lwoff = dot / 4;
152 					patch[patches].type = out.patch[x];
153 					patches++;
154 				}
155 				dot += 4;
156 			}
157 		}
158 		else
159 			dot += 4 * out.len;
160 	}
161 	| ABSOLUTE SYMBOL '=' exp .comment '\n'
162 	{
163 		setsym($2, $4.t, $4.value);
164 		if (pass2) {
165 			printf("\t\t\t/*\t");
166 			fwrite(line, strlen(line) - 1, 1, stdout);
167 			printf(" */\n");
168 		}
169 	}
170 	| SYMBOL '=' exp .comment '\n'
171 	{
172 		setsym($1, $3.t, $3.value);
173 		if (pass2) {
174 			printf("\t\t\t/*\t");
175 			fwrite(line, strlen(line) - 1, 1, stdout);
176 			printf(" */\n");
177 		}
178 	}
179 	| EXTERN SYMBOL {
180 		if (pass2) {
181 			printf("\t\t\t/*\t");
182 			fwrite(line, strlen(line) - 1, 1, stdout);
183 			printf(" */\n");
184 		}
185 		else {
186 			if (!pass2)
187 				externp[externs] = $2;
188 			setsym($2, Extern, externs++);
189 		}
190 	}
191 	;
192 
193 .comment: COMMENT
194 	| /* nothing */
195 	;
196 
197 .label:	SYMBOL ':' {
198 		if ($1->t != Unknown)
199 		{
200 			if (!pass2)
201 				yyerror("multiply defined symbol");
202 		}
203 		else {
204 			$1->t = Addr;
205 			$1->value = dot;
206 		}
207 	}
208 	| /* nothing */
209 	;
210 
211 set_cmd: SET { $$ = 3; }
212 	| CLEAR { $$ = 4; }
213 	;
214 
215 set_bit: CARRY { $$ = 0x400; }
216 	| TARGET { $$ = 0x200; }
217 	| ACK { $$ = 0x40; }
218 	| ATN { $$ = 0x8; }
219 	;
220 
221 set_list: set_list ',' set_bit { $$ = $1 | $3; }
222 	| set_list AND set_bit { $$ = $1 | $3; }
223 	| set_bit { $$ = $1; }
224 	;
225 
226 opcode: set_cmd set_list {
227 		out.len = 2;
228 		out.data[0] = (1L << 30) | ((long)$1 << 27) | $2;
229 		out.data[1] = 0;
230 		out.patch[0] = out.patch[1] = 0;
231 	}
232 	| DISCONNECT
233 	{
234 		out.len = 2;
235 		out.data[0] = 0x48020000L;
236 		out.data[1] = 0;
237 		out.patch[0] = out.patch[1] = 0;
238 	}
239 	| INT exp .cond {
240 		out.len = 2;
241 		out.data[0] = $3 | 0x98000000L;
242 		out.data[1] = $2.value;
243 		out.patch[0] = out.patch[1] = 0;
244 	}
245 	| INTFLY exp .cond {
246 		out.len = 2;
247 		out.data[0] = $3 | 0x98000000L | COND_INTFLY;
248 		out.data[1] = $2.value;
249 		out.patch[0] = out.patch[1] = 0;
250 	}
251 	| jump_or_call exp .cond {
252 		out.len = 2;
253 		out.data[0] = $1 | $3 | chkreladdr(1, &$2, 2, COND_REL);
254 		out.patch[0] = 0;
255 	}
256 	| jump_or_call REL '(' exp ')' .cond {
257 		out.len = 2;
258 		out.data[0] = $1 | $6 | COND_REL;
259 		out.data[1] = mkreladdr($4.value, 2);
260 		out.patch[0] = out.patch[1] = 0;
261 	}
262 	| MOVE exp ',' .ptr regexp ',' with_or_when phase {
263 		out.len = 2;
264 		out.data[0] = ($8 << 24) | $2.value | ($4 << 29) | MOVE_MODE;
265 		out.data[1] = $5.value;
266 		out.patch[0] = 0;
267 		out.patch[1] = patchtype($5.t);
268 	}
269 	| MOVE FROM exp ',' with_or_when phase {
270 		out.len = 2;
271 		out.data[0] = ($6 << 24) | (1L << 28) | MOVE_MODE;
272 		out.data[1] = $3.value;
273 		out.patch[0] = 0;
274 		out.patch[1] = patchtype($3.t);
275 	}
276 	| MOVE MEMORY exp ',' regexp ',' regexp {
277 		out.len = 3;
278 		out.data[0] = 0xc0000000L | $3.value;
279 		out.data[1] = $5.value;
280 		out.data[2] = $7.value;
281 		out.patch[0] = 0;
282 		out.patch[1] = patchtype($5.t);
283 		out.patch[2] = patchtype($7.t);
284 	}
285 	| MOVE regA TO regA		{ regmove($2, 2, $4, 0); }	/* do reg to sfbr moves using or 0 */
286 	| MOVE exp TO regA		{ regmove($4, 0, $4, &$2); }
287 	| MOVE regA '|' exp TO regA	{ regmove($2, 2, $6, &$4); }
288 	| MOVE regA '&' exp TO regA	{ regmove($2, 4, $6, &$4); }
289 	| MOVE regA '+' exp TO regA	{ regmove($2, 6, $6, &$4); }
290 	| MOVE regA '-' exp TO regA	{ regmove($2, 6, $6, &$4); }
291 	| MOVE regA '+' exp TO regA WITH CARRY	{
292 		regmove($2, 7, $6, &$4);
293 	}
294 	| MOVE regA '-' exp TO regA WITH CARRY	{
295 		$4.value = -$4.value;
296 		regmove($2, 7, $6, &$4);
297 	}
298 	| MOVE regA SHL TO regA		{ regmove($2, 1, $5, 0); }
299 	| MOVE regA SHR TO regA		{ regmove($2, 5, $5, 0); }
300 	| MOVE regA XOR exp TO regA	{ regmove($2, 3, $6, &$4); }
301 	| NOP {
302 		out.len = 2;
303 		out.data[0] = 0x80000000L;
304 		out.data[1] = 0;
305 		out.patch[0] = out.patch[1] = 0;
306 	}
307 	| RESELECT exp ',' exp {
308 		out.len = 2;
309 		out.data[0] = 0x40000000L | ((long)$2.value << 16) | (1L << 9) | chkreladdr(1, &$4, 2, IO_REL);
310 		out.patch[0] = 0;
311 	}
312 	| RESELECT exp ',' REL '(' exp ')' {
313 		out.len = 2;
314 		out.data[0] = 0x40000000L | IO_REL
315 		    | ((long)$2.value << 16) | (1L << 9);
316 		out.data[1] = mkreladdr($6.value, 2);
317 		out.patch[0] = out.patch[1] = 0;
318 	}
319 	| RESELECT FROM exp ',' exp {
320 		out.len = 2;
321 		out.data[0] = 0x40000000L | (1L << 25) | $3.value | chkreladdr(1, &$5, 2, IO_REL);
322 		out.patch[0] = 5;
323 	}
324 	| RESELECT FROM exp ',' REL '(' exp ')' {
325 		out.len = 2;
326 		out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $3.value;
327 		out.patch[0] = 5;
328 		out.data[1] = mkreladdr($7.value, 2);
329 		out.patch[1] = 0;
330 	}
331 	| RETURN .cond {
332 
333 		out.len = 2;
334 		out.data[0] = 0x90000000L | $2;
335 		out.data[1] = 0;
336 		out.patch[0] = out.patch[1] = 0;
337 	}
338 	| SELECT .atn exp ',' exp {
339 		out.len = 2;
340 		out.data[0] =
341 		    0x40000000L | ((long)$3.value << 16) | (1L << 9) | $2 | chkreladdr(1, &$5, 2, IO_REL);
342 		out.patch[0] = 0;
343 	}
344 	| SELECT .atn exp ',' REL '(' exp ')' {
345 		out.len = 2;
346 		out.data[0] = 0x40000000L | (1L << 26)
347 		    | ((long)$3.value << 16) | (1L << 9) | $2;
348 		out.data[1] = mkreladdr($7.value, 2);
349 		out.patch[0] = out.patch[1] = 0;
350 	}
351 	| SELECT .atn FROM exp ',' exp {
352 		out.len = 2;
353 		out.data[0] = 0x40000000L | (1L << 25) | $4.value | $2 | chkreladdr(1, &$6, 2, IO_REL);
354 		out.patch[0] = 5;
355 	}
356 	| SELECT .atn FROM exp ',' REL '(' exp ')' {
357 		out.len = 2;
358 		out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $4.value | $2;
359 		out.patch[0] = 5;
360 		out.data[1] = mkreladdr($8.value, 2);
361 		out.patch[1] = 0;
362 	}
363 	| WAIT DISCONNECT {
364 		out.len = 2;
365 		out.data[0] = 0x48000000L;
366 		out.data[1] = 0;
367 		out.patch[0] = out.patch[1] = 0;
368 	}
369 	| WAIT RESELECT exp {
370 		out.len = 2;
371 		out.data[0] = 0x50000000L | chkreladdr(1, &$3, 2, IO_REL);
372 		out.patch[0] = 0;
373 	}
374 	| WAIT RESELECT REL '(' exp ')' {
375 		out.len = 2;
376 		out.data[0] = 0x50000000L | (1L << 26);
377 		out.data[1] = mkreladdr($5.value, 2);
378 		out.patch[0] = out.patch[1] = 0;
379 	}
380 	| WAIT SELECT exp {
381 		out.len = 2;
382 		out.data[0] = 0x40000000L | (1L << 9) | chkreladdr(1, &$3, 2, IO_REL);
383 		out.patch[0] = 0;
384 	}
385 	| WAIT SELECT REL '(' exp ')' {
386 		out.len = 2;
387 		out.data[0] = 0x40000000L | (1L << 26) | (1L << 9);
388 		out.data[1] = mkreladdr($5.value, 2);
389 		out.patch[0] = out.patch[1] = 0;
390 	}
391 	| DEFW exp {
392 		out.len = 1;
393 		out.data[0] = $2.value;
394 		out.patch[0] = patchtype($2.t);
395 	}
396 	;
397 
398 .ptr:	PTR { $$ = 1; }
399 	| { $$ = 0; }
400 	;
401 
402 with_or_when: WITH
403 	| WHEN
404 	;
405 
406 jump_or_call: JUMP	 { $$ = 0x80000000L; }
407 	| CALL		 { $$ = 0x88000000L; }
408 	;
409 
410 condsfbr: byteexp { $$ = $1.value | COND_DATA; }
411 	| byteexp AND MASK byteexp { $$ = ($4.value << 8) | $1.value | COND_DATA; }
412 	;
413 
414 condphase: phase { $$ = ($1 << 24) | COND_PHASE; }
415 
416 .cond:    ',' IF ATN { $$ = COND_TRUE; }
417 	| ',' IF condphase { $$ = $3 | COND_TRUE; }
418 	| ',' IF CARRY { $$ = COND_CARRY | COND_TRUE; }
419 	| ',' IF condsfbr { $$ = $3 | COND_TRUE; }
420 	| ',' IF ATN AND condsfbr { $$ = $5 | COND_TRUE; }
421 	| ',' IF condphase AND condsfbr { $$ = $3 | $5 | COND_TRUE; }
422 	| ',' WHEN condphase { $$ = $3 | COND_WAIT | COND_TRUE; }
423 	| ',' WHEN CARRY { $$ = COND_CARRY | COND_WAIT | COND_TRUE; }
424 	| ',' WHEN condsfbr { $$ = $3 | COND_WAIT | COND_TRUE; }
425 	| ',' WHEN condphase AND condsfbr { $$ = $3 | $5 | COND_WAIT | COND_TRUE; }
426 	| ',' IF NOT ATN { $$ = 0; }
427 	| ',' IF NOT condphase { $$ = $4; }
428 	| ',' IF NOT CARRY { $$ = COND_CARRY; }
429 	| ',' IF NOT condsfbr { $$ = $4; }
430 	| ',' IF NOT ATN OR condsfbr { $$ = $6; }
431 	| ',' IF NOT condphase OR condsfbr { $$ = $4 | $6; }
432 	| ',' WHEN NOT condphase { $$ = $4 | COND_WAIT; }
433 	| ',' WHEN NOT CARRY { $$ = COND_CARRY | COND_WAIT; }
434 	| ',' WHEN NOT condsfbr { $$ = $4 | COND_WAIT; }
435 	| ',' WHEN NOT condphase OR condsfbr { $$ = $4 | $6 | COND_WAIT; }
436 	| { $$ = COND_TRUE; }
437 	;
438 
439 .opcode: opcode
440 	| { out.len = 0; }
441 	;
442 
443 regA:	reg
444 	| SFBR { $$ = 8; }
445 	;
446 
447 reg:	  SCNTL0	{ $$ = 0; }
448 	| SCNTL1	{ $$ = 1; }
449 	| SCNTL2	{ $$ = 2; }
450 	| SCNTL3	{ $$ = 3; }
451 	| SCID		{ $$ = 4; }
452 	| SXFER		{ $$ = 5; }
453 	| SDID		{ $$ = 6; }
454 	| GPREG		{ $$ = 7; }
455 	| SOCL		{ $$ = 9; }
456 	| SSID		{ $$ = 0xa; }
457 	| SBCL		{ $$ = 0xb; }
458 	| DSTAT		{ $$ = 0xc; }
459 	| SSTAT0	{ $$ = 0xd; }
460 	| SSTAT1	{ $$ = 0xe; }
461 	| SSTAT2	{ $$ = 0xf; }
462 	| DSA0		{ $$ = 0x10; }
463 	| DSA1		{ $$ = 0x11; }
464 	| DSA2		{ $$ = 0x12; }
465 	| DSA3		{ $$ = 0x13; }
466 	| ISTAT		{ $$ = 0x14; }
467 	| CTEST0	{ $$ = 0x18; }
468 	| CTEST1	{ $$ = 0x19; }
469 	| CTEST2	{ $$ = 0x1a; }
470 	| CTEST3	{ $$ = 0x1b; }
471 	| TEMP		{ $$ = 0x1c; }
472 	| DFIFO		{ $$ = 0x20; }
473 	| CTEST4	{ $$ = 0x21; }
474 	| CTEST5	{ $$ = 0x22; }
475 	| CTEST6	{ $$ = 0x23; }
476 	| DBC		{ $$ = 0x24; }
477 	| DCMD		{ $$ = 0x27; }
478 	| DNAD		{ $$ = 0x28; }
479 	| DSP		{ $$ = 0x2c; }
480 	| DSPS		{ $$ = 0x30; }
481 	| SCRATCHA0	{ $$ = 0x34; }
482 	| SCRATCHA1	{ $$ = 0x35; }
483 	| SCRATCHA2	{ $$ = 0x36; }
484 	| SCRATCHA3	{ $$ = 0x37; }
485 	| DMODE		{ $$ = 0x38; }
486 	| DIEN		{ $$ = 0x39; }
487 	| DWT		{ $$ = 0x3a; }
488 	| DCNTL		{ $$ = 0x3b; }
489 	| ADDER		{ $$ = 0x3c; }
490 	| SIEN0		{ $$ = 0x40; }
491 	| SIEN1		{ $$ = 0x41; }
492 	| SIST0		{ $$ = 0x42; }
493 	| SIST1		{ $$ = 0x43; }
494 	| SLPAR		{ $$ = 0x44; }
495 	| MACNTL	{ $$ = 0x46; }
496 	| GPCNTL	{ $$ = 0x47; }
497 	| STIME0	{ $$ = 0x48; }
498 	| STIME1	{ $$ = 0x49; }
499 	| RESPID	{ $$ = 0x4a; }
500 	| STEST0	{ $$ = 0x4c; }
501 	| STEST1	{ $$ = 0x4d; }
502 	| STEST2	{ $$ = 0x4e; }
503 	| STEST3	{ $$ = 0x4f; }
504 	| SIDL		{ $$ = 0x50; }
505 	| SODL		{ $$ = 0x54; }
506 	| SBDL		{ $$ = 0x58; }
507 	| SCRATCHB0	{ $$ = 0x5c; }
508 	| SCRATCHB1	{ $$ = 0x5d; }
509 	| SCRATCHB2	{ $$ = 0x5e; }
510 	| SCRATCHB3	{ $$ = 0x5f; }
511 	| SCRATCHC0	{ $$ = 0x60; }
512 	| SCRATCHC1	{ $$ = 0x61; }
513 	| SCRATCHC2	{ $$ = 0x62; }
514 	| SCRATCHC3	{ $$ = 0x63; }
515 	;
516 
517 .atn:	ATN		{ $$ = (1 << 24); }
518 	| /* nothing */ { $$ = 0; }
519 ;
520 
521 phase:	DATA_OUT 	{ $$ = 0; }
522 	| DATA_IN	{ $$ = 1; }
523 	| COMMAND 	{ $$ = 2; }
524 	| STATUS	{ $$ = 3; }
525 	| RESERVED_OUT 	{ $$ = 4; }
526 	| RESERVED_IN	{ $$ = 5; }
527 	| MESSAGE_OUT   { $$ = 6; }
528 	| MESSAGE_IN	{ $$ = 7; }
529 ;
530 
531 byteexp: exp
532 	{
533 		if (pass2 && ($1.value < 0 || $1.value > 255)) {
534 			if (wflag)
535 				yywarn("conversion causes truncation");
536 			$$.value = $1.value & 0xff;
537 		}
538 		else
539 			$$.value = $1.value;
540 	}
541 	;
542 
543 regexp:	exp
544 	| regA { $$.t = Reg; $$.value = $1; }
545 	;
546 
547 exp:	NUM { $$.t = Const; $$.value = $1; }
548 	| SYMBOL {
549 		$$.t = $1->t; $$.value = $1->value;
550 		if (pass2 && $1->t == Unknown)
551 		{
552 			yyerror("Undefined symbol %s", $1->name);
553 			$1->t = Error;
554 			$1->value = 0;
555 			$$.t = Error;
556 			$$.value = 0;
557 		}
558 	}
559         | exp '+' exp { $$ = eval($1, $3, '+'); }
560         | exp '-' exp { $$ = eval($1, $3, '-'); }
561         | exp '*' exp { $$ = eval($1, $3, '*'); }
562         | exp '/' exp { $$ = eval($1, $3, '/'); }
563         | '-' exp  %prec NEG { $$ = eval($2, $2, '_'); }
564         | '(' exp ')'        { $$ = $2; }
565 	| '~' exp %prec NEG { $$ = eval($2, $2, '~'); }
566 	;
567 %%
568 
569 struct {
570 	char *name;
571 	int tok;
572 } toktab[] =
573 {
574 	{ "when", WHEN },
575 	{ "data_out", DATA_OUT },
576 	{ "data_in", DATA_IN },
577 	{ "msg_out", MESSAGE_OUT },
578 	{ "msg_in", MESSAGE_IN },
579 	{ "cmd", COMMAND },
580 	{ "command", COMMAND },
581 	{ "status", STATUS },
582 	{ "move", MOVE },
583 	{ "select", SELECT },
584 	{ "reselect", RESELECT },
585 	{ "disconnect", DISCONNECT },
586 	{ "wait", WAIT },
587 	{ "set", SET },
588 	{ "clear", CLEAR },
589 	{ "with", WITH },
590 	{ "atn", ATN },
591 	{ "fail", FAIL },
592 	{ "carry", CARRY },
593 	{ "target", TARGET },
594 	{ "ack", ACK },
595 	{ "scntl0", SCNTL0 },
596 	{ "scntl1", SCNTL1 },
597 	{ "scntl2", SCNTL2 },
598 	{ "scntl3", SCNTL3 },
599 	{ "scid", SCID },
600 	{ "sxfer", SXFER },
601 	{ "sdid", SDID },
602 	{ "gpreg", GPREG },
603 	{ "sfbr", SFBR },
604 	{ "socl", SOCL },
605 	{ "ssid", SSID },
606 	{ "sbcl", SBCL },
607 	{ "dstat", DSTAT },
608 	{ "sstat0", SSTAT0 },
609 	{ "sstat1", SSTAT1 },
610 	{ "sstat2", SSTAT2 },
611 	{ "dsa", DSA0 },
612 	{ "dsa0", DSA0 },
613 	{ "dsa1", DSA1 },
614 	{ "dsa2", DSA2 },
615 	{ "dsa3", DSA3 },
616 	{ "istat", ISTAT },
617 	{ "ctest0", CTEST0 },
618 	{ "ctest1", CTEST1 },
619 	{ "ctest2", CTEST2 },
620 	{ "ctest3", CTEST3 },
621 	{ "temp", TEMP },
622 	{ "dfifo", DFIFO },
623 	{ "ctest4", CTEST4 },
624 	{ "ctest5", CTEST5 },
625 	{ "ctest6", CTEST6 },
626 	{ "dbc", DBC },
627 	{ "dcmd", DCMD },
628 	{ "dnad", DNAD },
629 	{ "dsp", DSP },
630 	{ "dsps", DSPS },
631 	{ "scratcha", SCRATCHA0 },
632 	{ "scratcha0", SCRATCHA0 },
633 	{ "scratcha1", SCRATCHA1 },
634 	{ "scratcha2", SCRATCHA2 },
635 	{ "scratcha3", SCRATCHA3 },
636 	{ "dmode", DMODE },
637 	{ "dien", DIEN },
638 	{ "dwt", DWT },
639 	{ "dcntl", DCNTL },
640 	{ "adder", ADDER },
641 	{ "sien0", SIEN0 },
642 	{ "sien1", SIEN1 },
643 	{ "sist0", SIST0 },
644 	{ "sist1", SIST1 },
645 	{ "slpar", SLPAR },
646 	{ "macntl", MACNTL },
647 	{ "gpcntl", GPCNTL },
648 	{ "stime0", STIME0 },
649 	{ "stime1", STIME1 },
650 	{ "respid", RESPID },
651 	{ "stest0", STEST0 },
652 	{ "stest1", STEST1 },
653 	{ "stest2", STEST2 },
654 	{ "stest3", STEST3 },
655 	{ "sidl", SIDL },
656 	{ "sodl", SODL },
657 	{ "sbdl", SBDL },
658 	{ "scratchb", SCRATCHB0 },
659 	{ "scratchb0", SCRATCHB0 },
660 	{ "scratchb1", SCRATCHB1 },
661 	{ "scratchb2", SCRATCHB2 },
662 	{ "scratchb3", SCRATCHB3 },
663 	{ "scratchc", SCRATCHC0 },
664 	{ "scratchc0", SCRATCHC0 },
665 	{ "scratchc1", SCRATCHC1 },
666 	{ "scratchc2", SCRATCHC2 },
667 	{ "scratchc3", SCRATCHC3 },
668 	{ "add", ADD },
669 	{ "addc", ADDC },
670 	{ "and", AND },
671 	{ "or", OR },
672 	{ "xor", XOR },
673 	{ "shl", SHL },
674 	{ "shr", SHR },
675 	{ "jump", JUMP },
676 	{ "call", CALL },
677 	{ "return", RETURN },
678 	{ "int", INT },
679 	{ "intfly", INTFLY },
680 	{ "not", NOT },
681 	{ "absolute", ABSOLUTE },
682 	{ "mask", MASK },
683 	{ "if", IF },
684 	{ "rel", REL },
685 	{ "ptr", PTR },
686 	{ "table", TABLE },
687 	{ "from", FROM },
688 	{ "memory", MEMORY },
689 	{ "to", TO },
690 	{ "nop", NOP },
691 	{ "extern", EXTERN },
692 	{ "defw", DEFW },
693 };
694 
695 #define TOKS (sizeof(toktab)/sizeof(toktab[0]))
696 
697 int lc;
698 int ll;
699 
700 void
yyrewind(void)701 yyrewind(void)
702 {
703 	rewind(in_f);
704 	ll = lc = 0;
705 	yyline = 0;
706 	dot = 0;
707 }
708 
709 int
yygetc(void)710 yygetc(void)
711 {
712 	if (lc == ll)
713 	{
714 	next:
715 		if (fgets(line, 500, in_f) == 0)
716 			return EOF;
717 		/* do nasty check for #line directives */
718 		if (strncmp(line, "#line", 5) == 0) {
719 			/* #line n "filename" */
720 			sscanf(line, "#line %d \"%[^\"]", &yyline, yyfilename);
721 			yyline--;
722 			goto next;
723 		}
724 		yyline++;
725 		ll = strlen(line);
726 		lc = 0;
727 	}
728 	return line[lc++];
729 }
730 
731 void
yyungetc(void)732 yyungetc(void)
733 {
734 	if (lc <= 0)
735 		exits("ungetc");
736 	lc--;
737 }
738 
739 int
yylex(void)740 yylex(void)
741 {
742 	char token[100];
743 	int tl = 0;
744 	int c;
745 	while ((c = yygetc()) != EOF && (c == ' ' || c == '\t'))
746 		;
747 	if (c == EOF)
748 		return 0;
749 	if (isalpha(c) || c == '_')
750 	{
751 		int x;
752 		do {
753 			token[tl++] = c;
754 		} while ((c = yygetc()) != EOF && (isalnum(c) || c == '_'));
755 		if (c == EOF)
756 			return 0;
757 		yyungetc();
758 		token[tl] = 0;
759 		for (x = 0; x < TOKS; x++)
760 			if (strcmp(toktab[x].name, token) == 0)
761 				return toktab[x].tok;
762 		/* must be a symbol */
763 		yylval.s = findsym(token);
764 		return SYMBOL;
765 	}
766 	else if (isdigit(c))
767 	{
768 		/* accept 0x<digits> or 0b<digits> 0<digits> or <digits> */
769 		int prefix = c == '0';
770 		unsigned long n = c - '0';
771 		int base = 10;
772 		for (;;)
773 		{
774 			c = yygetc();
775 			if (c == EOF)
776 				return 0;
777 			if (prefix)
778 			{
779 				prefix = 0;
780 				if (c == 'x') {
781 					base = 16;
782 					continue;
783 				}
784 				else if (c == 'b')
785 				{
786 					base = 2;
787 					continue;
788 				}
789 				else
790 					base = 8;
791 			}
792 			if (isdigit(c))
793 				c -= '0';
794 			else if (isalpha(c) && base > 10)
795 			{
796 				if (isupper(c))
797 					c = tolower(c);
798 				c = c - 'a' + 10;
799 			}
800 			else {
801 				yyungetc();
802 				yylval.n = n;
803 				return NUM;
804 			}
805 			if (c >= base)
806 				yyerror("illegal format number");
807 			n = n * base + c;
808 		}
809 	}
810 	else if (c == ';') {
811 		/* skip to end of line */
812 		while ((c = yygetc()) != EOF && c != '\n')
813 			;
814 		if (c != EOF)
815 			yyungetc();
816 		return COMMENT;
817 	}
818 	return c;
819 }
820 
821 void
yyerror(char * s,...)822 yyerror(char *s, ...)
823 {
824 	va_list ap;
825 
826 	va_start(ap, s);
827 	fprintf(stderr, "%s: %d: ", yyfilename, yyline);
828 	vfprintf(stderr, s, ap);
829 	if (putc('\n', stderr) < 0)
830 		exits("io");
831 	errors++;
832 	va_end(ap);
833 }
834 
835 void
yywarn(char * s,...)836 yywarn(char *s, ...)
837 {
838 	va_list ap;
839 
840 	va_start(ap, s);
841 	fprintf(stderr, "%s: %d: warning: ", yyfilename, yyline);
842 	vfprintf(stderr, s, ap);
843 	if (putc('\n', stderr) < 0)
844 		exits("io");
845 	warnings++;
846 	va_end(ap);
847 }
848 
849 void
p2error(int line,char * s)850 p2error(int line, char *s)
851 {
852 	USED(line);
853 	printf("/*\t%s */\n", s);
854 }
855 
856 void
main(int argc,char * argv[])857 main(int argc, char *argv[])
858 {
859 	int a;
860 	for (a = 1; a < argc; a++)
861 	{
862 		if (argv[a][0] == '-')
863 			switch (argv[a][1]) {
864 			case 'D':
865 				/* #defines for cpp */
866 				if (ncppopts >= MAXCPPOPTS) {
867 					fprintf(stderr, "too many cpp options\n");
868 					exits("options");
869 				}
870 				cppopts[ncppopts++] = argv[a];
871 				break;
872 			default:
873 				fprintf(stderr, "unrecognised option %s\n",
874 				    argv[a]);
875 				exits("options");
876 			}
877 		else
878 			break;
879 	}
880 	if (a != argc - 1)
881 	{
882 		fprintf(stderr, "usage: na [options] file\n");
883 		exits("options");
884 	}
885 	if (access(argv[a], 4) < 0) {
886 		fprintf(stderr, "can't read %s\n", argv[a]);
887 		exits("");
888 	}
889 	in_f = tmpfile();
890 	preprocess(argv[a], in_f);
891 	rewind(in_f);
892 	strcpy(yyfilename, argv[a]);
893 	yyparse();
894 	if (errors)
895 		exits("pass1");
896 	pass2 = 1;
897 	printf("unsigned long na_script[] = {\n");
898 	yyrewind();
899 	yyparse();
900 	printf("};\n");
901 	printf("\n");
902 	printf("#define NA_SCRIPT_SIZE %d\n", dot / 4);
903 	printf("\n");
904 	fixup();
905 /*
906 	assemble();
907 */
908 	exits(errors ? "pass2" : "");
909 }
910 
911 void
preprocess(char * in,FILE * out)912 preprocess(char *in, FILE *out)
913 {
914 	Waitmsg *w;
915 	char **argv;
916 
917 	if (fork() == 0) {
918 		/* child */
919 		dup(fileno(out), 1);
920 		argv = (char **)malloc(sizeof(char *) * (ncppopts + 5));
921 		argv[0] = "cpp";
922 		memcpy(&argv[1], cppopts, sizeof(char *) * ncppopts);
923 		argv[ncppopts + 1] = "-+";
924 		argv[ncppopts + 2] = "-N";
925 		argv[ncppopts + 3] = in;
926 		argv[ncppopts + 4] = 0;
927 		exec("/bin/cpp", argv);
928 		fprintf(stderr, "failed to exec cpp (%R)\n");
929 		exits("exec");
930 	}
931 	w = wait();
932 	free(w);
933 }
934 
935 struct sym *
findsym(char * name)936 findsym(char *name)
937 {
938 	struct sym *s;
939 	for (s = symlist; s; s = s->next)
940 		if (strcmp(name, s->name) == 0)
941 			return s;
942 	s = (struct sym *)malloc(sizeof(*s));
943 	s->name = strdup(name);
944 	s->t = Unknown;
945 	s->set = 0;
946 	s->next = symlist;
947 	symlist = s;
948 	return s;
949 }
950 
951 void
setsym(struct sym * s,Type t,long v)952 setsym(struct sym *s, Type t, long v)
953 {
954 	if (pass2) {
955 		if (t == Unknown || t == Error)
956 			yyerror("can't resolve symbol");
957 		else {
958 			s->t = t;
959 			s->value = v;
960 		}
961 	}
962 	else {
963 		if (s->set)
964 			yyerror("multiply defined symbol");
965 		s->set = 1;
966 		s->t = t;
967 		s->value = v;
968 	}
969 }
970 
971 int
mk24bitssigned(long * l)972 mk24bitssigned(long *l)
973 {
974 	if (*l < 0) {
975 		if ((*l & 0xff800000L) != 0xff800000L) {
976 			*l = 0;
977 			return 0;
978 		}
979 		else
980 			*l = (*l) & 0xffffffL;
981 	}
982 	else if (*l > 0xffffffL) {
983 		*l = 0;
984 		return 0;
985 	}
986 	return 1;
987 }
988 
989 static Type addresult[5][5] = {
990 /*		Const	Addr	Table   Extern	Reg */
991 /* Const */	Const,	Addr,	Table,	Error,  Reg,
992 /* Addr */	Addr,	Error,	Error,	Error,  Error,
993 /* Table */	Table,	Error,	Error,	Error,  Error,
994 /* Extern */	Error,	Error,	Error,	Error,	Error,
995 /* Reg */	Reg,	Error,  Error,  Error,	Error,
996 };
997 
998 static Type subresult[5][5] = {
999 /*		Const	Addr	Table   Extern	Reg */
1000 /* Const */	Const,	Error,	Error,	Error,  Error,
1001 /* Addr */	Addr,	Const,	Error,	Error,	Error,
1002 /* Table */	Table,	Error,	Const,	Error,	Error,
1003 /* Extern */	Error,	Error,	Error,	Const,	Error,
1004 /* Reg */	Error,	Error,  Error,  Error,	Error,
1005 };
1006 
1007 static Type muldivresult[5][5] = {
1008 /*		Const	Addr	Table   Extern */
1009 /* Const */	Const,	Error,	Error,	Error,	Error,
1010 /* Addr */	Error,	Error,	Error,	Error,	Error,
1011 /* Table */	Error,	Error,	Error,	Error,	Error,
1012 /* Extern */	Error,	Error,	Error,	Error,	Error,
1013 /* Reg */	Error,	Error,	Error,	Error,	Error,
1014 };
1015 
1016 static Type negresult[] = {
1017 /* Const */	Const,
1018 /* Addr */	Error,
1019 /* Table */	Error,
1020 /* Extern */	Error,
1021 /* Reg */	Error,
1022 };
1023 
1024 int
patchtype(Type t)1025 patchtype(Type t)
1026 {
1027 	switch (t) {
1028 	case Addr:
1029 		return 1;
1030 	case Reg:
1031 		return 2;
1032 	case Extern:
1033 		return 4;
1034 	default:
1035 		return 0;
1036 	}
1037 }
1038 
1039 struct expval
eval(struct expval a,struct expval b,char op)1040 eval(struct expval a, struct expval b, char op)
1041 {
1042 	struct expval c;
1043 
1044 	if (a.t == Unknown || b.t == Unknown) {
1045 		c.t = Unknown;
1046 		c.value = 0;
1047 	}
1048 	else if (a.t == Error || b.t == Error) {
1049 		c.t = Error;
1050 		c.value = 0;
1051 	}
1052 	else {
1053 		switch (op) {
1054 		case '+':
1055 			c.t = addresult[a.t][b.t];
1056 			break;
1057 		case '-':
1058 			c.t = subresult[a.t][b.t];
1059 			break;
1060 		case '*':
1061 		case '/':
1062 			c.t = muldivresult[a.t][b.t];
1063 			break;
1064 		case '_':
1065 		case '~':
1066 			c.t = negresult[a.t];
1067 			break;
1068 		default:
1069 			c.t = Error;
1070 			break;
1071 		}
1072 		if (c.t == Error) {
1073 			if (pass2)
1074 				yyerror("type clash in evaluation");
1075 			c.value = 0;
1076 		}
1077 		else {
1078 			switch (op) {
1079 			case '+':
1080 				c.value = a.value + b.value;
1081 				break;
1082 			case '-':
1083 				c.value = a.value - b.value;
1084 				break;
1085 			case '*':
1086 				c.value = a.value * b.value;
1087 				break;
1088 			case '/':
1089 				c.value = a.value / b.value;
1090 				break;
1091 			case '_':
1092 				c.value = -a.value;
1093 				break;
1094 			case '~':
1095 				c.value = ~a.value;
1096 				break;
1097 			}
1098 		}
1099 	}
1100 	return c;
1101 }
1102 
1103 void
regmove(unsigned char src_reg,unsigned char op,unsigned char dst_reg,struct expval * imm)1104 regmove(unsigned char src_reg, unsigned char op,
1105     unsigned char dst_reg, struct expval *imm)
1106 {
1107 	unsigned char func, reg;
1108 	int immdata;
1109 	out.len = 2;
1110 	if (src_reg == 8) {
1111 		func = 5;
1112 		reg = dst_reg;
1113 	}
1114 	else if (dst_reg == 8) {
1115 		func = 6;
1116 		reg = src_reg;
1117 	}
1118 	else {
1119 		if (pass2 && src_reg != dst_reg)
1120 			yyerror("Registers must be the same");
1121 		func = 7;
1122 		reg = src_reg;
1123 	}
1124 	immdata = imm ? (imm->value & 0xff) : 0;
1125 	out.data[0] = 0x40000000L
1126 	    | ((long)func << 27)
1127 	    | ((long)op << 24)
1128 	    | ((long)reg << 16)
1129 	    | ((long)(immdata) << 8);
1130 	out.data[1] = 0;
1131 	out.patch[0] = (imm && imm->t == Extern) ? 3 : 0;
1132 	out.patch[1] = 0;
1133 }
1134 
1135 long
mkreladdr(long addr,int len)1136 mkreladdr(long addr, int len)
1137 {
1138 	long rel;
1139 	rel = addr - (dot + 4 * len);
1140 	mk24bitssigned(&rel);
1141 	return rel;
1142 }
1143 
1144 long
chkreladdr(int d,struct expval * e,int len,long relrv)1145 chkreladdr(int d, struct expval *e, int len, long relrv)
1146 {
1147 	if (e->t == Addr) {
1148 		out.data[d] = mkreladdr(e->value, len);
1149 		out.patch[d] = 0;
1150 		return relrv;
1151 	} else {
1152 		out.data[d] = e->value;
1153 		out.patch[d] = patchtype(e->t);
1154 		return 0;
1155 	}
1156 }
1157 
1158 void
fixup(void)1159 fixup(void)
1160 {
1161 	struct sym *s;
1162 	int p;
1163 	printf("struct na_patch na_patches[] = {\n");
1164 	for (p = 0; p < patches; p++) {
1165 		printf("\t{ 0x%.4x, %d }, /* %.8lx */\n",
1166 		    patch[p].lwoff, patch[p].type, patch[p].lwoff * 4L);
1167 	}
1168 	if (patches == 0) {
1169 		printf("\t{ 0, 0 },\n");
1170 	}
1171 	printf("};\n");
1172 	printf("#define NA_PATCHES %d\n", patches);
1173 	printf("\n");
1174 	if (externs) {
1175 		printf("enum na_external {\n");
1176 		for (p = 0; p < externs; p++) {
1177 			printf("\tX_%s,\n", externp[p]->name);
1178 		}
1179 		printf("};\n");
1180 	}
1181 	/* dump all labels (symbols of type Addr) as E_<Name> */
1182 	for (s = symlist; s; s = s->next)
1183 		if (s->t == Addr)
1184 			break;
1185 	if (s) {
1186 		printf("\nenum {\n");
1187 		while (s) {
1188 			if (s->t == Addr)
1189 				printf("\tE_%s = %ld,\n", s->name, s->value);
1190 			s = s->next;
1191 		}
1192 		printf("};\n");
1193 	}
1194 	/* dump all Consts as #define A_<Name> value */
1195 	for (s = symlist; s; s = s->next)
1196 		if (s->t == Const)
1197 			printf("#define A_%s %ld\n", s->name, s->value);
1198 }
1199 
1200