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