1 /* NCR53c8xx assembler */
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)
18 #define IO_REL (1L << 26)
20 #define MOVE_MODE (1L << 27)
25 void yyerror(char *, ...);
26 void yywarn(char *, ...);
27 void p2error(int line, char *);
30 int type; /* 0 - direct, 1 - indirect 2 - table indirect */
34 typedef enum Type { Const, Addr, Table, Extern, Reg, Unknown, Error } Type;
44 struct sym *findsym(char *name);
47 void newsym(struct sym *s, Type t, long v);
51 unsigned long data[3];
52 unsigned char patch[3];
56 #define MAX_PATCHES 1000
57 struct na_patch patch[MAX_PATCHES];
67 struct expval eval(struct expval a, struct expval b, char op);
69 int patchtype(Type t);
75 struct sym *externp[100];
77 void regmove(unsigned char src_reg, unsigned char op,
78 unsigned char dst_reg, struct expval *imm);
80 void preprocess(char *in, FILE *out);
82 int mk24bitssigned(long *l);
83 long mkreladdr(long value, int len);
84 long chkreladdr(int d, struct expval *e, int len, long relrv);
91 char *cppopts[MAXCPPOPTS];
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
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
128 %type <e> exp byteexp regexp
130 /* Grammar follows */
132 input: /* empty string */
136 line: .label .opcode .comment '\n'
140 for (x = 0; x < out.len; x++) {
141 printf("/* %.4x */ 0x%.8lxL,",
146 strlen(line) - 1, 1, stdout);
151 patch[patches].lwoff = dot / 4;
152 patch[patches].type = out.patch[x];
161 | ABSOLUTE SYMBOL '=' exp .comment '\n'
163 setsym($2, $4.t, $4.value);
165 printf("\t\t\t/*\t");
166 fwrite(line, strlen(line) - 1, 1, stdout);
170 | SYMBOL '=' exp .comment '\n'
172 setsym($1, $3.t, $3.value);
174 printf("\t\t\t/*\t");
175 fwrite(line, strlen(line) - 1, 1, stdout);
181 printf("\t\t\t/*\t");
182 fwrite(line, strlen(line) - 1, 1, stdout);
187 externp[externs] = $2;
188 setsym($2, Extern, externs++);
198 if ($1->t != Unknown)
201 yyerror("multiply defined symbol");
211 set_cmd: SET { $$ = 3; }
215 set_bit: CARRY { $$ = 0x400; }
216 | TARGET { $$ = 0x200; }
221 set_list: set_list ',' set_bit { $$ = $1 | $3; }
222 | set_list AND set_bit { $$ = $1 | $3; }
223 | set_bit { $$ = $1; }
226 opcode: set_cmd set_list {
228 out.data[0] = (1L << 30) | ((long)$1 << 27) | $2;
230 out.patch[0] = out.patch[1] = 0;
235 out.data[0] = 0x48020000L;
237 out.patch[0] = out.patch[1] = 0;
241 out.data[0] = $3 | 0x98000000L;
242 out.data[1] = $2.value;
243 out.patch[0] = out.patch[1] = 0;
247 out.data[0] = $3 | 0x98000000L | COND_INTFLY;
248 out.data[1] = $2.value;
249 out.patch[0] = out.patch[1] = 0;
251 | jump_or_call exp .cond {
253 out.data[0] = $1 | $3 | chkreladdr(1, &$2, 2, COND_REL);
256 | jump_or_call REL '(' exp ')' .cond {
258 out.data[0] = $1 | $6 | COND_REL;
259 out.data[1] = mkreladdr($4.value, 2);
260 out.patch[0] = out.patch[1] = 0;
262 | MOVE exp ',' .ptr regexp ',' with_or_when phase {
264 out.data[0] = ($8 << 24) | $2.value | ($4 << 29) | MOVE_MODE;
265 out.data[1] = $5.value;
267 out.patch[1] = patchtype($5.t);
269 | MOVE FROM exp ',' with_or_when phase {
271 out.data[0] = ($6 << 24) | (1L << 28) | MOVE_MODE;
272 out.data[1] = $3.value;
274 out.patch[1] = patchtype($3.t);
276 | MOVE MEMORY exp ',' regexp ',' regexp {
278 out.data[0] = 0xc0000000L | $3.value;
279 out.data[1] = $5.value;
280 out.data[2] = $7.value;
282 out.patch[1] = patchtype($5.t);
283 out.patch[2] = patchtype($7.t);
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);
294 | MOVE regA '-' exp TO regA WITH CARRY {
295 $4.value = -$4.value;
296 regmove($2, 7, $6, &$4);
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); }
303 out.data[0] = 0x80000000L;
305 out.patch[0] = out.patch[1] = 0;
307 | RESELECT exp ',' exp {
309 out.data[0] = 0x40000000L | ((long)$2.value << 16) | (1L << 9) | chkreladdr(1, &$4, 2, IO_REL);
312 | RESELECT exp ',' REL '(' exp ')' {
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;
319 | RESELECT FROM exp ',' exp {
321 out.data[0] = 0x40000000L | (1L << 25) | $3.value | chkreladdr(1, &$5, 2, IO_REL);
324 | RESELECT FROM exp ',' REL '(' exp ')' {
326 out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $3.value;
328 out.data[1] = mkreladdr($7.value, 2);
334 out.data[0] = 0x90000000L | $2;
336 out.patch[0] = out.patch[1] = 0;
338 | SELECT .atn exp ',' exp {
341 0x40000000L | ((long)$3.value << 16) | (1L << 9) | $2 | chkreladdr(1, &$5, 2, IO_REL);
344 | SELECT .atn exp ',' REL '(' exp ')' {
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;
351 | SELECT .atn FROM exp ',' exp {
353 out.data[0] = 0x40000000L | (1L << 25) | $4.value | $2 | chkreladdr(1, &$6, 2, IO_REL);
356 | SELECT .atn FROM exp ',' REL '(' exp ')' {
358 out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $4.value | $2;
360 out.data[1] = mkreladdr($8.value, 2);
365 out.data[0] = 0x48000000L;
367 out.patch[0] = out.patch[1] = 0;
369 | WAIT RESELECT exp {
371 out.data[0] = 0x50000000L | chkreladdr(1, &$3, 2, IO_REL);
374 | WAIT RESELECT REL '(' exp ')' {
376 out.data[0] = 0x50000000L | (1L << 26);
377 out.data[1] = mkreladdr($5.value, 2);
378 out.patch[0] = out.patch[1] = 0;
382 out.data[0] = 0x40000000L | (1L << 9) | chkreladdr(1, &$3, 2, IO_REL);
385 | WAIT SELECT REL '(' exp ')' {
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;
393 out.data[0] = $2.value;
394 out.patch[0] = patchtype($2.t);
398 .ptr: PTR { $$ = 1; }
406 jump_or_call: JUMP { $$ = 0x80000000L; }
407 | CALL { $$ = 0x88000000L; }
410 condsfbr: byteexp { $$ = $1.value | COND_DATA; }
411 | byteexp AND MASK byteexp { $$ = ($4.value << 8) | $1.value | COND_DATA; }
414 condphase: phase { $$ = ($1 << 24) | COND_PHASE; }
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; }
447 reg: SCNTL0 { $$ = 0; }
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; }
477 | DCMD { $$ = 0x27; }
478 | DNAD { $$ = 0x28; }
480 | DSPS { $$ = 0x30; }
481 | SCRATCHA0 { $$ = 0x34; }
482 | SCRATCHA1 { $$ = 0x35; }
483 | SCRATCHA2 { $$ = 0x36; }
484 | SCRATCHA3 { $$ = 0x37; }
485 | DMODE { $$ = 0x38; }
486 | DIEN { $$ = 0x39; }
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; }
517 .atn: ATN { $$ = (1 << 24); }
518 | /* nothing */ { $$ = 0; }
521 phase: DATA_OUT { $$ = 0; }
522 | DATA_IN { $$ = 1; }
523 | COMMAND { $$ = 2; }
525 | RESERVED_OUT { $$ = 4; }
526 | RESERVED_IN { $$ = 5; }
527 | MESSAGE_OUT { $$ = 6; }
528 | MESSAGE_IN { $$ = 7; }
533 if (pass2 && ($1.value < 0 || $1.value > 255)) {
535 yywarn("conversion causes truncation");
536 $$.value = $1.value & 0xff;
544 | regA { $$.t = Reg; $$.value = $1; }
547 exp: NUM { $$.t = Const; $$.value = $1; }
549 $$.t = $1->t; $$.value = $1->value;
550 if (pass2 && $1->t == Unknown)
552 yyerror("Undefined symbol %s", $1->name);
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, '~'); }
575 { "data_out", DATA_OUT },
576 { "data_in", DATA_IN },
577 { "msg_out", MESSAGE_OUT },
578 { "msg_in", MESSAGE_IN },
580 { "command", COMMAND },
581 { "status", STATUS },
583 { "select", SELECT },
584 { "reselect", RESELECT },
585 { "disconnect", DISCONNECT },
593 { "target", TARGET },
595 { "scntl0", SCNTL0 },
596 { "scntl1", SCNTL1 },
597 { "scntl2", SCNTL2 },
598 { "scntl3", SCNTL3 },
608 { "sstat0", SSTAT0 },
609 { "sstat1", SSTAT1 },
610 { "sstat2", SSTAT2 },
617 { "ctest0", CTEST0 },
618 { "ctest1", CTEST1 },
619 { "ctest2", CTEST2 },
620 { "ctest3", CTEST3 },
623 { "ctest4", CTEST4 },
624 { "ctest5", CTEST5 },
625 { "ctest6", CTEST6 },
631 { "scratcha", SCRATCHA0 },
632 { "scratcha0", SCRATCHA0 },
633 { "scratcha1", SCRATCHA1 },
634 { "scratcha2", SCRATCHA2 },
635 { "scratcha3", SCRATCHA3 },
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 },
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 },
677 { "return", RETURN },
679 { "intfly", INTFLY },
681 { "absolute", ABSOLUTE },
688 { "memory", MEMORY },
691 { "extern", EXTERN },
695 #define TOKS (sizeof(toktab)/sizeof(toktab[0]))
715 if (fgets(line, 500, in_f) == 0)
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);
745 while ((c = yygetc()) != EOF && (c == ' ' || c == '\t'))
749 if (isalpha(c) || c == '_')
754 } while ((c = yygetc()) != EOF && (isalnum(c) || c == '_'));
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);
768 /* accept 0x<digits> or 0b<digits> 0<digits> or <digits> */
769 int prefix = c == '0';
770 unsigned long n = c - '0';
794 else if (isalpha(c) && base > 10)
806 yyerror("illegal format number");
811 /* skip to end of line */
812 while ((c = yygetc()) != EOF && c != '\n')
822 yyerror(char *s, ...)
827 fprintf(stderr, "%s: %d: ", yyfilename, yyline);
828 vfprintf(stderr, s, ap);
829 if (putc('\n', stderr) == EOF)
841 fprintf(stderr, "%s: %d: warning: ", yyfilename, yyline);
842 vfprintf(stderr, s, ap);
843 if (putc('\n', stderr) == EOF)
850 p2error(int line, char *s)
853 printf("/*\t%s */\n", s);
857 main(int argc, char *argv[])
860 for (a = 1; a < argc; a++)
862 if (argv[a][0] == '-')
863 switch (argv[a][1]) {
865 /* #defines for cpp */
866 if (ncppopts >= MAXCPPOPTS) {
867 fprintf(stderr, "too many cpp options\n");
870 cppopts[ncppopts++] = argv[a];
873 fprintf(stderr, "unrecognised option %s\n",
882 fprintf(stderr, "usage: na [options] file\n");
885 if (access(argv[a], 4) < 0) {
886 fprintf(stderr, "can't read %s\n", argv[a]);
890 preprocess(argv[a], in_f);
892 strcpy(yyfilename, argv[a]);
897 printf("unsigned long na_script[] = {\n");
902 printf("#define NA_SCRIPT_SIZE %d\n", dot / 4);
908 exits(errors ? "pass2" : "");
912 preprocess(char *in, FILE *out)
920 argv = (char **)malloc(sizeof(char *) * (ncppopts + 5));
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");
939 for (s = symlist; s; s = s->next)
940 if (strcmp(name, s->name) == 0)
942 s = (struct sym *)malloc(sizeof(*s));
943 s->name = strdup(name);
952 setsym(struct sym *s, Type t, long v)
955 if (t == Unknown || t == Error)
956 yyerror("can't resolve symbol");
964 yyerror("multiply defined symbol");
972 mk24bitssigned(long *l)
975 if ((*l & 0xff800000L) != 0xff800000L) {
980 *l = (*l) & 0xffffffL;
982 else if (*l > 0xffffffL) {
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,
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,
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,
1016 static Type negresult[] = {
1040 eval(struct expval a, struct expval b, char op)
1044 if (a.t == Unknown || b.t == Unknown) {
1048 else if (a.t == Error || b.t == Error) {
1055 c.t = addresult[a.t][b.t];
1058 c.t = subresult[a.t][b.t];
1062 c.t = muldivresult[a.t][b.t];
1066 c.t = negresult[a.t];
1074 yyerror("type clash in evaluation");
1080 c.value = a.value + b.value;
1083 c.value = a.value - b.value;
1086 c.value = a.value * b.value;
1089 c.value = a.value / b.value;
1104 regmove(unsigned char src_reg, unsigned char op,
1105 unsigned char dst_reg, struct expval *imm)
1107 unsigned char func, reg;
1114 else if (dst_reg == 8) {
1119 if (pass2 && src_reg != dst_reg)
1120 yyerror("Registers must be the same");
1124 immdata = imm ? (imm->value & 0xff) : 0;
1125 out.data[0] = 0x40000000L
1126 | ((long)func << 27)
1129 | ((long)(immdata) << 8);
1131 out.patch[0] = (imm && imm->t == Extern) ? 3 : 0;
1136 mkreladdr(long addr, int len)
1139 rel = addr - (dot + 4 * len);
1140 mk24bitssigned(&rel);
1145 chkreladdr(int d, struct expval *e, int len, long relrv)
1148 out.data[d] = mkreladdr(e->value, len);
1152 out.data[d] = e->value;
1153 out.patch[d] = patchtype(e->t);
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);
1169 printf("\t{ 0, 0 },\n");
1172 printf("#define NA_PATCHES %d\n", patches);
1175 printf("enum na_external {\n");
1176 for (p = 0; p < externs; p++) {
1177 printf("\tX_%s,\n", externp[p]->name);
1181 /* dump all labels (symbols of type Addr) as E_<Name> */
1182 for (s = symlist; s; s = s->next)
1186 printf("\nenum {\n");
1189 printf("\tE_%s = %ld,\n", s->name, s->value);
1194 /* dump all Consts as #define A_<Name> value */
1195 for (s = symlist; s; s = s->next)
1197 printf("#define A_%s %ld\n", s->name, s->value);