Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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) < 0)
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) < 0)
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