]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/na/na.y
aux/ms2, aux/na: fix warnings
[plan9front.git] / sys / src / cmd / aux / na / na.y
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
701 yyrewind(void)
702 {
703         rewind(in_f);
704         ll = lc = 0;
705         yyline = 0;
706         dot = 0;
707 }
708
709 int
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
732 yyungetc(void)
733 {
734         if (lc <= 0)
735                 exits("ungetc");
736         lc--;
737 }
738
739 int
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
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) == EOF)
830                 exits("io");
831         errors++;
832         va_end(ap);
833 }
834
835 void
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) == EOF)
844                 exits("io");
845         warnings++;
846         va_end(ap);
847 }
848
849 void
850 p2error(int line, char *s)
851 {
852         USED(line);
853         printf("/*\t%s */\n", s);
854 }
855
856 void
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
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 *
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
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
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
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
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
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
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
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
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