2 /*******************************************************
4 * a56 - a DSP56001 assembler
6 * Written by Quinn C. Jensen
9 *******************************************************/
12 * Copyright (C) 1990-1994 Quinn C. Jensen
14 * Permission to use, copy, modify, distribute, and sell this software
15 * and its documentation for any purpose is hereby granted without fee,
16 * provided that the above copyright notice appear in all copies and
17 * that both that copyright notice and this permission notice appear
18 * in supporting documentation. The author makes no representations
19 * about the suitability of this software for any purpose. It is
20 * provided "as is" without express or implied warranty.
25 * a56.y - The YACC grammar for the assembler.
27 * Note: This module requires a "BIG" version of YACC. I had to
28 * recompile YACC in the largest mode available.
32 * MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure
33 * out which form to use.
40 unsigned int w0, w1; /* workspace for the actual generated code */
41 BOOL uses_w1; /* says whether w1 is alive */
42 unsigned int pc; /* current program counter */
43 int seg; /* current segment P: X: Y: or L: */
44 int expr_seg; /* segment of current expression */
46 int just_rep = 0; /* keeps track of REP instruction */
47 int hot_rreg = -1; /* rreg loaded by prev inst. or -1 */
48 int hot_nreg = -1; /* nreg loaded by prev inst. or -1 */
49 int hot_mreg = -1; /* mreg loaded by prev inst. or -1 */
50 int prev_hot_rreg = -1; /* rreg loaded by prev inst. or -1 */
51 int prev_hot_nreg = -1; /* nreg loaded by prev inst. or -1 */
52 int prev_hot_mreg = -1; /* mreg loaded by prev inst. or -1 */
54 int substatement = 0; /* in a substatement */
55 BOOL long_symbolic_expr = FALSE; /* a parser flag */
56 char *new_include = NULL; /* file to be included */
60 char segs[] = "uPXYL*";
61 extern BOOL list_on_next; /* listing to turn on or off */
62 BOOL list_on; /* listing on at the moment */
63 extern char *cur_line; /* points to line being lex'd */
64 char list_buf[1024 + 80]; /* listing buffer */
65 char list_buf2[1024 + 80]; /* listing buffer for two-line code */
66 BOOL uses_buf2 = FALSE; /* list_buf2 is alive */
67 BOOL list_print_line = FALSE; /* whether or not to print line in listing */
68 char *spaces(), *luntab();
77 #define R_DATA_ALU_ACCUM 0x0008
78 #define R_CTL_REG 0x0010
79 #define R_FUNKY_CTL_REG 0x0020
86 /* registers to which short immediate move is an unsigned int */
88 /* registers to which short immediate move is an signed frac */
89 #define R_SFRAC 0x2000
93 int ival; /* integer value */
94 struct n n; /* just like in struct sym */
95 double dval; /* floating point value */
96 char *sval; /* string */
97 int cval; /* character */
98 char cond; /* condition */
100 int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
101 int sdx, sdy, lsd, ab, xreg, yreg;
111 %token <n> CHEX CDEC FRAC
112 %token <ival> AREG BREG MREG NREG RREG XREG YREG
113 %token <ival> OP OPA OPP
114 %token <cond> OP_JCC OP_JSCC OP_TCC
228 %type <n> num num_or_sym
229 %type <n> num_or_sym_expr
234 %type <ival> abs_addr abs_short_addr io_short_addr
235 %type <ival> a_b x_or_y ea b5_10111_max
236 %type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
237 %type <ival> ea_short
238 %type <ival> prog_ctl_reg
239 %type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
240 %type <ival> mpy_arg mpy_srcs plus_minus
242 %type <ival> funky_ctl_reg tcc_sd space
243 %type <sval> opt_label
246 %type <ea> movep_ea_pp
260 /*%%%********************* top syntax ***********************/
269 if(pass == 2 && list_on && list_print_line) {
270 printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
271 list_buf, substatement == 0 ? luntab(cur_line) : "");
273 printf(ldebug ? "\n(%s|)\n" : "%s\n",
275 list_buf[0] = list_buf2[0] = '\0';
279 list_print_line = TRUE;
280 list_on = list_on_next;
282 if(NOT check_psect(seg, pc) && pass == 2)
283 yyerror("%04X: psect violation", pc);
287 if(pass == 2 && list_on && list_print_line) {
288 printf(ldebug ? "\n(%s" : "%s", list_buf);
289 if(substatement == 0)
290 printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line));
292 printf(ldebug ? ")\n" : "\n");
294 printf(ldebug ? "\n(%s|)\n" : "%s\n",
296 list_buf[0] = list_buf2[0] = '\0';
300 list_print_line = TRUE;
301 list_on = list_on_next;
302 if(NOT check_psect(seg, pc) && pass == 2)
303 yyerror("%04X: psect violation", pc);
306 {curline++; substatement = 0;}
311 {sprintf(list_buf, "%s", spaces(0));}
313 {list_print_line = FALSE;}
315 {long_symbolic_expr = FALSE;}
316 | label_field operation_field
319 gencode(seg, pc, w0);
320 sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0));
323 gencode(seg, pc, w1);
324 sprintf(list_buf2, "%c:%04X %s", segs[seg], pc,
325 printcode(w1 & 0xFFFFFF));
334 w0 = w1 = 0; uses_w1 = FALSE;
335 long_symbolic_expr = FALSE;}
337 {sym_def($1, INT, seg, pc);
339 if(pass == 2 && list_on) {
340 sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8));
341 long_symbolic_expr = FALSE;
351 curline = $2.val.i - 1;}
356 {sym_def($1, $3.type, ANY, $3.val.i, $3.val.f);
358 if(pass == 2 && list_on) {
360 sprintf(list_buf, "%06X%s",
364 sprintf(list_buf, "%10g%s", $3.val.f,
368 {int ival = n2int($2);
369 if($2.type == UNDEF) {
370 yyerror("illegal forward reference");
371 } else if (ival <= 1) {
372 yyerror("%d: illegal alignment", ival);
375 pc += ival - pc % ival;
377 if(pass == 2 && list_on)
378 sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
382 {struct psect *pp = find_psect($2);
385 yyerror("%s: undefined psect", $2);
390 if(pass == 2 && list_on)
391 sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
395 | OP_PSECT SYM space expr ':' expr
396 {new_psect($2, $3, n2int($4), n2int($6));
397 if(pass == 2 && list_on)
398 sprintf(list_buf, "%c:%04X %04X%s",
399 segs[$3], n2int($4), n2int($6), spaces(14-8+4+1));
404 if(pass == 2 && list_on)
405 sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
408 | OP_ORG space expr ',' space expr
411 if(pass == 2 && list_on)
412 sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
415 | label_field OP_DC dc_list
416 | label_field OP_DS expr
418 if(pass == 2 && list_on)
419 sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
422 | opt_label OP_DSM expr
423 {int size = n2int($3);
428 pc += (align - (pc % align));
431 { sym_def($1, INT, seg, pc);
436 | OP_PAGE num ',' num ',' num ',' num
437 {if(pass == 2 && list_on) {
438 sprintf(list_buf, "%s", spaces(0));
441 {if(pass == 2 && list_on) {
442 printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
443 spaces(0), luntab(cur_line));
444 list_print_line = FALSE;
446 include($2); /* free($2); */
449 {if(pass == 2 && list_on) {
450 sprintf(list_buf, "%s", spaces(0));
455 : dc_list ',' dc_stuff
461 {int len = strlen($1), i; char *cp; w0 = 0;
463 len++; /* force empty word */
464 for(i = 0, cp = $1; i < len; i++, cp++) {
465 w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
466 if(i % 3 == 2 || i == len - 1) {
468 if(list_on) sprintf(list_buf, "%c:%04X %06X%s",
471 gencode(seg, pc, w0);
478 {int frac = n2frac($1);
481 sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc,
482 frac & 0xFFFFFF, spaces(14-6+5));
484 gencode(seg, pc, frac);
501 {sym_def($1, INT, seg, pc);
508 | /* empty */ {$$ = NULL;}
513 {prev_hot_rreg = hot_rreg;
514 prev_hot_nreg = hot_nreg;
515 prev_hot_mreg = hot_mreg;
516 hot_rreg = hot_nreg = hot_mreg = -1;
525 | parallel_ok parallel_move
528 /*%%%************* instructions that allow parallel moves ****************/
533 {w0 |= 0x80 | $2 << 2;}
535 {w0 |= 0x81 | $2 << 2;}
537 {w0 |= 0x82 | $2 << 2;}
539 {w0 |= 0x83 | $2 << 2;}
542 {w0 |= 0x04 | $2 << 3;}
544 {w0 |= 0x00 | $2 << 3;}
549 {w0 |= 0x01 | $2 << 3;}
551 {w0 |= 0x05 | $2 << 3;}
553 {w0 |= 0x07 | $2 << 3;}
556 {w0 |= 0x11 | $2 << 3;}
558 {w0 |= 0x12 | $2 << 3;}
560 {w0 |= 0x13 | $2 << 3;}
562 {w0 |= 0x16 | $2 << 3;}
564 {w0 |= 0x17 | $2 << 3;}
567 {w0 |= 0x02 | $2 << 3;}
569 {w0 |= 0x03 | $2 << 3;}
571 {w0 |= 0x06 | $2 << 3;}
574 {w0 |= 0x46 | $2 << 3;}
576 {w0 |= 0x42 | $2 << 3;}
578 {w0 |= 0x43 | $2 << 3;}
581 {w0 |= 0x22 | $2 << 3;}
583 {w0 |= 0x23 | $2 << 3;}
585 {w0 |= 0x26 | $2 << 3;}
587 {w0 |= 0x27 | $2 << 3;}
590 {w0 |= 0x32 | $2 << 3;}
592 {w0 |= 0x33 | $2 << 3;}
594 {w0 |= 0x36 | $2 << 3;}
596 {w0 |= 0x37 | $2 << 3;}
599 {w0 |= 0x21 | $2 << 3;}
601 {w0 |= 0x25 | $2 << 3;}
604 mpy_arg : plus_minus mpy_srcs ',' a_b
605 {$$ = $1 | $4 << 1 | $2 << 2;}
619 {switch ($1 << 4 | $3) {
620 case 0x00: $$ = 0x0; break;
622 case 0x10: $$ = 0x2; break;
624 yyerror("illegal source operands");
628 {switch ($1 << 4 | $3) {
629 case 0x00: $$ = 0x1; break;
631 case 0x10: $$ = 0x3; break;
633 yyerror("illegal source operands");
637 {switch ($1 << 4 | $3) {
638 case 0x00: $$ = 0x5; break;
639 case 0x01: $$ = 0x4; break;
640 case 0x10: $$ = 0x6; break;
641 case 0x11: $$ = 0x7; break;
644 {switch ($1 << 4 | $3) {
645 case 0x00: $$ = 0x5; break;
646 case 0x01: $$ = 0x6; break;
647 case 0x10: $$ = 0x4; break;
648 case 0x11: $$ = 0x7; break;
652 op8_1 : BBBB ',' AAAA
661 {$$ = 0x8 | $1 << 2 | $3;}
663 {$$ = 0xA | $1 << 2 | $3;}
666 op8_2 : BBBB ',' AAAA
671 {$$ = 0x8 | $1 << 2 | $3;}
673 {$$ = 0xA | $1 << 2 | $3;}
691 {$$ = 0x0 | $1 << 2 | $3;}
693 {$$ = 0x2 | $1 << 2 | $3;}
719 yyerror("instruction not allowed after REP");}
725 /*%%%************** non-parallel arithmetic and logical ********************/
728 : OP_NORM RREG ',' a_b
729 {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
731 {w0 |= 0x018040 | $2 << 3;}
732 | or_op ix ',' funky_ctl_reg
733 {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;}
734 | and_op ix ',' funky_ctl_reg
735 {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;}
746 /*%%%******************************* control instructions **********************/
751 w0 |= 0x0BC0A0 | $1 << 0;
753 w0 |= 0x0F0000 | $1 << 12;
757 w0 |= 0x0AC0A0 | $1 << 0;
759 w0 |= 0x0E0000 | $1 << 12;
774 | OP_JSSET control_args
776 | OP_JSCLR control_args
778 | OP_JSET control_args
780 | OP_JCLR control_args
810 {int ival = n2int($1);
811 w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
812 if(ival > 0xFFF && pass == 2) {
813 yywarning("warning: immediate operand truncated");
817 {w0 |= 0x06C000 | $1.r6 << 8;
818 hot_rreg = hot_nreg = hot_mreg = -1;
820 | x_or_y ea_no_ext ',' abs_addr
821 {w0 |= 0x064000 | $2 << 8 | $1 << 6;
823 | x_or_y abs_short_addr ',' abs_addr /* allow forced */
824 {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
826 * $$$ oops, can't check expr_seg because both abs_short_addr and
829 if($2 > 0x003F && pass == 2)
830 yywarning("warning: address operand truncated");
832 | x_or_y abs_addr ',' abs_addr
833 {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
835 * $$$ oops, can't check expr_seg because both abs_short_addr and
838 if($2 > 0x003F && pass == 2)
839 yywarning("warning: address operand truncated");
845 {int ival = n2int($1);
846 w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
847 if(ival > 0xFFF && pass == 2) {
848 yywarning("warning: immediate operand truncated");
851 {w0 |= 0x06C020 | $1.r6 << 8;
852 hot_rreg = hot_nreg = hot_mreg = -1;}
854 {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
856 {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
857 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
858 $1 == 1 && expr_seg != YDATA))
859 yywarning("warning: space mismatch");
860 if($2 > 0x003F && pass == 2)
861 yywarning("warning: address operand truncated");
863 | x_or_y abs_short_addr /* forced */
864 {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
865 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
866 $1 == 1 && expr_seg != YDATA))
867 yywarning("warning: space mismatch");
868 if($2 > 0x003F && pass == 2)
869 yywarning("warning: address operand truncated");
874 : b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
875 {w0 |= $1 << 0 | $3 << 6;
878 | b5_10111_max ',' regs ',' abs_addr
879 {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
880 hot_rreg = hot_nreg = hot_mreg = -1;
886 : abs_addr /* in pass 2 can always discern size. */
887 /* Sometimes in pass one, too. But since */
888 /* address extension is always used for the */
889 /* branch target, pass 1 can assume the */
890 /* symbol value will fit; warning in pass 2 */
892 {if($1 != -1) { /* symbol defined */
893 w0 |= ($1 & 0x3F) << 8;
898 if($1 > 0x003F && pass == 2)
899 yywarning("warning: address operand truncated");
904 if($1 > 0x3F && pass == 2)
905 yywarning("warning: address operand truncated");
906 w0 |= 0x000080 | ($1 & 0x3F) << 8;
910 if($1 < 0xFFC0 && pass == 2)
911 yywarning("warning: address operand truncated");
912 w0 |= 0x008080 | ($1 & 0x3F) << 8;
915 {w0 |= 0x004080 | $1 << 8;}
918 /*%%%**************************** bit instructions ***************************/
932 : b5_10111_max ',' x_or_y p6_ea_a6
933 {w0 |= $1 << 0 | $3 << 6;
935 | b5_10111_max ',' regs
936 {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
940 : io_short_addr /* must be forced to tell from abs_addr */
942 w0 |= ($1 & 0x3F) << 8 | 0x008000;
943 if($1 < 0xFFC0 && pass == 2)
944 yywarning("warning: address operand truncated");
946 | abs_short_addr /* must be forced to tell from abs_addr */
948 w0 |= ($1 & 0x3F) << 8 | 0x000000;
949 if($1 > 0x003F && pass == 2)
950 yywarning("warning: address operand truncated");
952 | ea /* can use abs_addr */
956 /*%%%************************** move instructions **********************/
959 : OP_MOVEP movep_args
960 | OP_MOVEM movem_args
961 | OP_MOVEC movec_args
962 | OP_LUA ea_short ',' regs
963 {w0 |= 0x044010 | $2 << 8 | $4.r4;}
970 {w0 |= 0x020000 | $1 << 3;}
971 | tcc_sd RREG ',' RREG
972 {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
976 : regs /* a_b */ ',' regs /* a_b */
977 {hot_rreg = hot_nreg = hot_mreg = -1;
978 if($1.flags & R_AB && $3.flags & R_AB) {
980 yyerror("source and dest must be different");
982 } else if($1.flags & R_XREG && $3.flags & R_AB) {
983 $$ = 0x8 | $1.xreg << 2 | $3.ab;
984 } else if($1.flags & R_YREG && $3.flags & R_AB) {
985 $$ = 0xA | $1.yreg << 2 | $3.ab;
987 yyerror("illegal TCC operands");
991 sd3 : regs /* XREG */ ',' regs /* a_b */
992 {hot_rreg = hot_nreg = hot_mreg = -1;
993 if($1.flags & R_XREG && $3.flags & R_AB) {
994 $$ = $1.xreg << 2 | $3.ab;
995 } else if($1.flags & R_YREG && $3.flags & R_AB) {
996 $$ = $1.yreg << 2 | 2 | $3.ab;
1001 : x_or_y ea ',' regs /* ctl_reg */
1002 {if(NOT ($4.flags & R_CTL_REG))
1003 yyerror("bad MOVEC target register");
1004 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
1005 $1 == 1 && expr_seg != YDATA))
1006 yywarning("warning: space mismatch");
1008 w0 |= 0x05C020 | $4.ctl_reg;
1010 w0 |= 0x05C060 | $4.ctl_reg;
1012 | regs /* ctl_reg */ ',' x_or_y ea
1013 {hot_rreg = hot_nreg = hot_mreg = -1;
1014 if(NOT ($1.flags & R_CTL_REG))
1015 yyerror("bad MOVEC source register");
1017 w0 |= 0x054020 | $1.ctl_reg;
1019 w0 |= 0x054060 | $1.ctl_reg;
1021 | ix ',' regs /* ctl_reg */
1022 {int ival = n2int($1);
1023 if(NOT ($3.flags & R_CTL_REG))
1024 yyerror("bad MOVEC target register");
1025 if(ival < 256 && NOT long_symbolic_expr) {
1026 w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg;
1028 w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
1029 uses_w1++; w1 = ival & 0xFFFF;
1031 | x_or_y abs_short_addr ',' regs /* ctl_reg */
1033 w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
1035 w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
1037 if(NOT ($4.flags & R_CTL_REG))
1038 yyerror("bad MOVEC target register");
1039 if($2 > 0x003F && pass == 2)
1040 yywarning("warning: address operand truncated");
1042 | regs /* ctl_reg */ ',' x_or_y abs_short_addr
1043 {hot_rreg = hot_nreg = hot_mreg = -1;
1045 w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
1047 w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
1049 if(NOT ($1.flags & R_CTL_REG))
1050 yyerror("bad MOVEC source register");
1051 if($4 > 0x003F && pass == 2)
1052 yywarning("warning: address operand truncated");
1054 | regs /* ctl_reg */ ',' regs
1055 {if($1.flags & R_CTL_REG) {
1056 w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
1057 } else if($3.flags & R_CTL_REG) {
1058 w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
1059 } else if($1.flags & $3.flags & R_CTL_REG) {
1061 w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 |
1064 yyerror("MOVEC must reference a control reg");
1069 : x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
1071 switch($2.pp << 1 | $5.pp) {
1073 yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
1075 case 1: /* ea, pp */
1076 w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
1078 if($2.mode == 0x003000) {
1086 case 2: /* pp, ea */
1087 w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
1089 if($5.mode == 0x003000) {
1098 | ix ',' x_or_y num_or_sym
1100 w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 |
1104 | PMEM ea ',' x_or_y num_or_sym
1106 w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);}
1107 | x_or_y movep_ea_pp ',' PMEM ea
1109 if($2.mode != 0x003000 && $2.mode != 0)
1110 yyerror("illegal MOVEP");
1111 w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
1112 | regs ',' x_or_y num_or_sym
1113 {hot_rreg = hot_nreg = hot_mreg = -1;
1115 w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 |
1116 (n2int($4) & 0x3F);}
1117 | x_or_y movep_ea_pp ',' regs
1118 {hot_rreg = hot_nreg = hot_mreg = -1;
1121 yyerror("illegal MOVEP");
1122 w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
1127 {if($1 != UNDEF && $1 >= 0xFFC0) {
1128 /* defined symbol or constant, in i/o range */
1132 /* either out of i/o range or symbol not */
1133 /* yet defined: assume ea extension */
1138 | io_short_addr /* forced i/o short */
1141 if($1 < 0xFFC0 && pass == 2)
1142 yywarning("warning: address operand truncated");
1151 : regs ',' PMEM ea_a6
1152 {w0 |= 0x070000 | 0 << 15 | $1.r6;}
1153 | PMEM ea_a6 ',' regs
1154 {hot_rreg = hot_nreg = hot_mreg = -1;
1155 w0 |= 0x070000 | 1 << 15 | $4.r6;}
1158 /*%%%**************** memory reference fields ************************/
1162 {int ival = n2int($1);
1163 $$ = ival; if(ival > 0x17)
1164 yyerror("%d: illegal bit number", ival);}
1174 /*%%%**************** effective address fields ************************/
1180 {w0 |= ($1 & 0x3F) << 8;
1181 if($1 > 0x003F && pass == 2)
1182 yywarning("warning: address operand truncated");
1190 {w0 |= $1 & 0xFFF; $$ = 0;
1191 if($1 > 0x0FFF && pass == 2)
1192 yywarning("warning: address operand truncated");
1211 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1213 | '(' RREG '+' NREG ')'
1214 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1215 if($4 == prev_hot_nreg) yywarning("warning: n%d just loaded", $4);
1216 if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
1218 if($2 != $4) yyerror("Rn and Nn must be same number");}
1220 {if($3 == prev_hot_rreg) yywarning("warning: r%d just loaded", $3);
1221 if($3 == prev_hot_mreg) yywarning("warning: m%d just loaded", $3);
1226 : '(' RREG ')' '-' NREG
1227 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1228 if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
1229 if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
1232 if($2 != $5) yyerror("Rn and Nn must be same number");}
1233 | '(' RREG ')' '+' NREG
1234 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1235 if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
1236 if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
1239 if($2 != $5) yyerror("Rn and Nn must be same number");}
1241 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1242 if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
1246 {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
1247 if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
1252 /*%%%******************* register fields ******************************/
1256 {$$.r6 = $$.r5 = 0x04 | $1;
1259 $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;}
1261 {$$.r6 = $$.r5 = 0x06 | $1;
1264 $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;}
1268 $$.r6 = $$.r5 = 0x08 | 0;
1271 $$.r6 = $$.r5 = 0x08 | 4;
1274 $$.r6 = $$.r5 = 0x08 | 2;
1277 $$.flags = R_R6|R_R5|R_UINT;}
1281 $$.r6 = $$.r5 = 0x08 | 1; break;
1283 $$.r6 = $$.r5 = 0x08 | 5; break;
1285 $$.r6 = $$.r5 = 0x08 | 3; break;
1287 $$.flags = R_R6|R_R5|R_UINT;}
1289 {$$.r6 = $$.r5 = 0x0E;
1290 $$.sdx = $$.sdy = 0x2;
1293 $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
1295 {$$.r6 = $$.r5 = 0x0F;
1296 $$.sdx = $$.sdy = 0x3;
1299 $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
1301 {$$.r6 = $$.r5 = 0x10 | $1;
1303 $$.flags = R_R6|R_R5|R_R4|R_UINT;
1306 {$$.r6 = $$.r5 = 0x18 | $1;
1308 $$.flags = R_R6|R_R5|R_R4|R_UINT;
1314 $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;
1319 $$.ctl_reg = 0x18 | $1;
1320 $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
1367 /*%%%************************* parallel moves *************/
1380 i_move : ix ',' regs
1381 {int ival = n2int($1);
1382 int frac = n2frac($1);
1384 BOOL shortform = FALSE;
1385 if($3.flags & R_CTL_REG) {
1386 yyerror("please use MOVEC for control register moves");
1389 if(($3.flags & R_SFRAC) && $1.type == FLT) {
1390 if((frac & 0xFFFF) == 0 &&
1391 NOT long_symbolic_expr) {
1398 if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) {
1407 w0 |= 0x200000 | (value & 0xFF) << 8 |
1410 w0 |= 0x400000 | 0x00F400 |
1411 ($3.r5 >> 3 & 3) << 20 |
1413 uses_w1++; w1 = value;
1417 r_move : regs ',' regs
1419 if($3.flags & R_CTL_REG) {
1420 yyerror("please use MOVEC for control register moves");
1423 if($1.flags & R_R5 & $3.flags)
1424 w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
1426 yyerror("illegal R move");
1431 {w0 |= 0x204000 | $1 << 8;}
1435 : x_or_y ea ',' regs
1436 {w0 |= 0x40C000 | $1 << 19;
1437 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
1438 $1 == 1 && expr_seg != YDATA))
1439 yywarning("warning: space mismatch");
1440 if($4.flags & R_CTL_REG) {
1441 yyerror("please use MOVEC for control register moves");
1444 w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
1445 | x_or_y abs_short_addr ',' regs
1446 {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
1447 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
1448 $1 == 1 && expr_seg != YDATA))
1449 yywarning("warning: space mismatch");
1450 if($4.flags & R_CTL_REG) {
1451 yyerror("please use MOVEC for control register moves");
1454 if($2 > 0x003F && pass == 2)
1455 yywarning("warning: address operand truncated");
1456 w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
1457 | regs ',' x_or_y ea
1458 {hot_rreg = hot_nreg = hot_mreg = -1;
1459 w0 |= 0x404000 | $3 << 19;
1460 if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
1461 $3 == 1 && expr_seg != YDATA))
1462 yywarning("warning: space mismatch");
1463 if($1.flags & R_CTL_REG) {
1464 yyerror("please use MOVEC for control register moves");
1467 w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
1468 | regs ',' x_or_y abs_short_addr
1469 {hot_rreg = hot_nreg = hot_mreg = -1;
1470 w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
1471 if($1.flags & R_CTL_REG) {
1472 yyerror("please use MOVEC for control register moves");
1475 if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
1476 $3 == 1 && expr_seg != YDATA))
1477 yywarning("warning: space mismatch");
1478 if($4 > 0x003F && pass == 2)
1479 yywarning("warning: address operand truncated");
1480 w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
1482 {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
1484 if($3.flags & R_CTL_REG) {
1485 yyerror("please use MOVEC for control register moves");
1488 uses_w1++; w1 = n2frac($1);
1493 : x_or_y /* XMEM */ ea ',' regs regs /* a_b */ ',' YREG
1494 {hot_rreg = hot_nreg = hot_mreg = -1;
1495 if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
1496 $1 == 1 && expr_seg != YDATA))
1497 yywarning("warning: space mismatch");
1498 if($1 == 0 && $5.flags & R_AB) {
1499 w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
1502 yyerror("illegal X:R move");
1504 | ix ',' regs regs /* a_b */ ',' YREG
1505 {hot_rreg = hot_nreg = hot_mreg = -1;
1506 if($4.flags & R_AB) {
1507 w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
1510 w1 |= n2frac($1) & 0xFFFFFF;
1512 yyerror("illegal X:R move");
1514 | regs ',' x_or_y /* XMEM */ ea regs /* a_b */ ',' regs/*YREG*/
1515 {hot_rreg = hot_nreg = hot_mreg = -1;
1516 if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
1517 $3 == 1 && expr_seg != YDATA))
1518 yywarning("warning: space mismatch");
1519 if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
1520 $7.flags & R_YREG) {
1521 w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
1523 } else if($1.flags & R_AB && $3 == 0 &&
1524 $5.flags & R_XREG && $7.flags & R_AB) {
1525 if($5.xreg != 0) yyerror("must use X0");
1526 if($1.ab == 0 && $7.ab == 0)
1528 else if($1.ab == 1 && $7.ab == 1)
1531 yyerror("illegal X:R move");
1533 yyerror("illegal X:R move");
1537 ry_move : regs /* a_b */ ',' regs /* XREG */ YMEM ea ',' regs
1538 {hot_rreg = hot_nreg = hot_mreg = -1;
1539 if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
1540 w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 |
1543 yyerror("illegal R:Y move");
1545 | regs /* a_b */ ',' regs /* XREG */ ix ',' regs
1546 {hot_rreg = hot_nreg = hot_mreg = -1;
1547 if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
1548 w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
1551 w1 |= n2frac($4) & 0xFFFFFF;
1553 yyerror("illegal R:Y move");
1555 | regs /* a_b */ ',' regs /* XREG */ regs ',' YMEM ea
1556 {hot_rreg = hot_nreg = hot_mreg = -1;
1557 if($1.flags & R_AB && $3.flags & R_XREG) {
1558 w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
1560 } else if ($1.flags & R_YREG && $3.flags & R_AB &&
1562 if($1.yreg != 0) yyerror("must use Y0");
1563 if($3.ab == 0 && $4.ab == 0)
1565 else if($3.ab == 1 && $4.ab == 1)
1568 yyerror("illegal R:Y move");
1570 yyerror("illegal R:Y move");
1575 : LMEM ea ',' regs /* lsd */
1576 {if($4.flags & R_CTL_REG) {
1577 yyerror("please use MOVEC for control register moves");
1580 w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
1581 | regs /* lsd */ ',' LMEM ea
1582 {hot_rreg = hot_nreg = hot_mreg = -1;
1583 if($1.flags & R_CTL_REG) {
1584 yyerror("please use MOVEC for control register moves");
1587 w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
1588 | LMEM abs_short_addr ',' regs /* lsd */
1589 {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
1590 if($4.flags & R_CTL_REG) {
1591 yyerror("please use MOVEC for control register moves");
1594 if($2 > 0x003F && pass == 2)
1595 yywarning("warning: address operand truncated");
1596 w0 |= ($2 & 0x3F) << 8;}
1597 | regs /* lsd */ ',' LMEM abs_short_addr
1598 {hot_rreg = hot_nreg = hot_mreg = -1;
1599 w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
1600 if($1.flags & R_CTL_REG) {
1601 yyerror("please use MOVEC for control register moves");
1604 if($4 > 0x003F && pass == 2)
1605 yywarning("warning: address operand truncated");
1606 w0 |= ($4 & 0x3F) << 8;}
1610 : x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs YMEM ea /*ea_strange*/ ',' regs
1611 {int eax = $2, eay = $6,
1612 regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
1613 regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
1614 hot_rreg = hot_nreg = hot_mreg = -1;
1615 if((eax & 0x400) == (eay & 0x400))
1616 yyerror("registers must be in opposite halves");
1617 if(!($4.flags & (R_AB | R_XREG)))
1618 yyerror("invalid X move register");
1619 if(!($8.flags & (R_AB | R_YREG)))
1620 yyerror("invalid Y move register");
1621 if($4.flags & R_AB &&
1624 yyerror("duplicate destination register");
1625 w0 = w0 & 0xFF | 0xC08000; /* both write */
1626 w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
1627 | x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs regs ',' YMEM ea /*ea_strange*/
1628 {int eax = $2, eay = $8,
1629 regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
1630 regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
1631 hot_rreg = hot_nreg = hot_mreg = -1;
1632 if((eax & 0x400) == (eay & 0x400))
1633 yyerror("registers must be in opposite halves");
1634 if(!($4.flags & (R_AB | R_XREG)))
1635 yyerror("invalid X move register");
1636 if(!($5.flags & (R_AB | R_YREG)))
1637 yyerror("invalid Y move register");
1638 w0 = w0 & 0xFF | 0x808000; /* X:write, Y:read */
1639 w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
1640 | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ YMEM ea /*ea_strange*/ ',' regs
1641 {int eax = $4, eay = $6,
1642 regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
1643 regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
1644 hot_rreg = hot_nreg = hot_mreg = -1;
1645 if((eax & 0x400) == (eay & 0x400))
1646 yyerror("registers must be in opposite halves");
1647 if(!($1.flags & (R_AB | R_XREG)))
1648 yyerror("invalid X move register");
1649 if(!($8.flags & (R_AB | R_YREG)))
1650 yyerror("invalid Y move register");
1651 w0 = w0 & 0xFF | 0xC00000; /* X:read, Y:write */
1652 w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
1653 | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ regs ',' YMEM ea /*ea_strange*/
1654 {int eax = $4, eay = $8,
1655 regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
1656 regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
1657 hot_rreg = hot_nreg = hot_mreg = -1;
1658 if((eax & 0x400) == (eay & 0x400))
1659 yyerror("registers must be in opposite halves");
1660 if(!($1.flags & (R_AB | R_XREG)))
1661 yyerror("invalid X move register");
1662 if(!($5.flags & (R_AB | R_YREG)))
1663 yyerror("invalid Y move register");
1664 w0 = w0 & 0xFF | 0x800000; /* both read */
1665 w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
1668 /*%%%******* absolute address and immediate data fields ************/
1679 {$$ = $2; expr_seg = ANY;}
1681 {$$.val.i = n2int($3) & 0xFF;
1684 long_symbolic_expr = FALSE;}
1687 ix_long : '#' '>' expr
1688 {$$ = $3; expr_seg = ANY;}
1713 {$$ = sym_ref($1); free($1);}
1715 {$$.type = INT; $$.val.i = $1; $$.seg = expr_seg;}
1720 {$$ = $1; expr_seg = $1.seg;}
1724 long_symbolic_expr++;
1728 {$$.type = INT; $$.val.i = $1 & 0xFFFFFF; expr_seg = $$.seg = ANY;}
1730 {$$.type = INT; $$.val.i = pc; expr_seg = $$.seg = ANY;}
1732 {$$.type = FLT; $$.val.f = acos(-1.0); expr_seg = $$.seg = ANY;}
1736 : OP_INT '(' expr ')'
1739 $$.val.i = $3.val.i;
1741 $$.val.i = $3.val.f;
1745 {$$ = binary_op($1, '|', $3);}
1747 {$$ = binary_op($1, '^', $3);}
1749 {$$ = binary_op($1, '&', $3);}
1751 {$$ = binary_op($1, SHR, $3);}
1753 {$$ = binary_op($1, SHL, $3);}
1755 {$$ = binary_op($1, '-', $3);}
1757 {$$ = binary_op($1, '+', $3);}
1759 {$$ = binary_op($1, '%', $3);}
1761 {$$ = binary_op($1, '/', $3);}
1763 {$$ = binary_op($1, '*', $3);}
1764 | '-' expr %prec '~'
1765 {$$ = unary_op('-', $2);}
1767 {$$ = unary_op('~', $2);}
1768 | OP_SIN '(' expr ')'
1769 {$$ = unary_op('s', $3);}
1770 | OP_COS '(' expr ')'
1771 {$$ = unary_op('c', $3);}
1772 | OP_TAN '(' expr ')'
1773 {$$ = unary_op('t', $3);}
1774 | OP_ASIN '(' expr ')'
1775 {$$ = unary_op('S', $3);}
1776 | OP_ACOS '(' expr ')'
1777 {$$ = unary_op('C', $3);}
1778 | OP_ATAN '(' expr ')'
1779 {$$ = unary_op('T', $3);}
1780 | OP_EXP '(' expr ')'
1781 {$$ = unary_op('e', $3);}
1782 | OP_LN '(' expr ')'
1783 {$$ = unary_op('l', $3);}
1784 | OP_LOG '(' expr ')'
1785 {$$ = unary_op('L', $3);}
1786 | OP_ABS '(' expr ')'
1787 {$$ = unary_op('a', $3);}
1788 | OP_POW '(' expr ',' expr ')'
1789 {$$ = binary_op($3, 'p', $5);}
1796 /*%%%****************** end ******************************/
1802 #include <sys/signal.h>
1806 struct n binary_op(a1, op, a2)
1812 double farg1, farg2;
1814 if(a1.type == UNDEF || a2.type == UNDEF) {
1815 result.type = UNDEF;
1819 iarg1 = a1.type == INT ? a1.val.i : a1.val.f;
1820 iarg2 = a2.type == INT ? a2.val.i : a2.val.f;
1822 farg1 = a1.type == INT ? a1.val.i : a1.val.f;
1823 farg2 = a2.type == INT ? a2.val.i : a2.val.f;
1825 /* figure out target segment */
1827 if(a1.seg == a2.seg)
1828 result.seg = a1.seg;
1829 else if(a1.seg == ANY)
1830 result.seg = a2.seg;
1831 else if(a2.seg == ANY)
1832 result.seg = a1.seg;
1836 /* promote to float automatically */
1838 if(a1.type != a2.type) {
1839 if(a1.type == INT) {
1840 a1.val.f = a1.val.i; /* truncate */
1843 a2.val.f = a2.val.i; /* truncate */
1846 result.type = a1.type;
1852 if(result.type == INT) result.val.i = a1.val.i + a2.val.i;
1853 else result.val.f = a1.val.f + a2.val.f;
1856 if(result.type == INT) result.val.i = a1.val.i - a2.val.i;
1857 else result.val.f = a1.val.f - a2.val.f;
1860 if(result.type == INT) result.val.i = a1.val.i * a2.val.i;
1861 else result.val.f = a1.val.f * a2.val.f;
1864 if(result.type == INT) result.val.i = a1.val.i / a2.val.i;
1865 else result.val.f = a1.val.f / a2.val.f;
1868 result.val.i = iarg1 % iarg2;
1872 result.val.i = iarg1 << iarg2;
1876 result.val.i = iarg1 >> iarg2;
1880 result.val.i = iarg1 | iarg2;
1884 result.val.i = iarg1 & iarg2;
1888 result.val.i = iarg1 ^ iarg2;
1892 result.val.f = pow(farg1, farg2);
1904 longjmp(unary_env, 1);
1907 char *unary_name(op)
1910 case 's': return "sin";
1911 case 'c': return "cos";
1912 case 't': return "tan";
1913 case 'S': return "asin";
1914 case 'C': return "acos";
1915 case 'T': return "atan";
1916 case 'e': return "exp";
1917 case 'l': return "ln";
1918 case 'L': return "log";
1919 case 'a': return "abs";
1923 struct n unary_op(op, a1)
1931 if(a1.type == UNDEF) {
1932 result.type = UNDEF;
1936 result.seg = a1.seg;
1940 orig = signal(SIGFPE, sigfpu);
1941 if(setjmp(unary_env)) {
1942 yyerror("floating point exception in function %s", unary_name(op));
1943 result.val.i = result.val.f = 0;
1945 farg = a1.type == INT ? (double)a1.val.i : a1.val.f;
1948 result.type = a1.type;
1949 if(a1.type == INT) result.val.i = -a1.val.i;
1950 else result.val.f = -a1.val.f;
1953 result.type = a1.type;
1954 if(a1.type == INT) result.val.i = ~a1.val.i;
1955 else result.val.f = ~(int)a1.val.f;
1958 result.type = a1.type;
1959 if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i;
1960 else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f;
1964 result.val.f = sin(farg);
1968 result.val.f = cos(farg);
1972 result.val.f = tan(farg);
1976 result.val.f = asin(farg);
1980 result.val.f = acos(farg);
1984 result.val.f = atan(farg);
1988 result.val.f = exp(farg);
1992 result.val.f = log(farg);
1996 result.val.f = log10(farg);
2000 signal(SIGFPE, orig);
2010 else if(n.type == INT)
2019 double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f;
2023 else if(n.type == INT)
2025 else if(n.val.f == -1.0)
2028 adval -= (double)(int)adval;
2029 adval *= (double)0x800000;
2038 extern struct {int n; char *name;} tok_tab[];
2041 char *tok_print(tok)
2045 static char buf[32];
2052 sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF);
2055 for(i = 0; i < n_tok; i++) {
2056 if(tok == tok_tab[i].n)
2057 return tok_tab[i].name;
2063 yyerror(s, a0, a1, a2, a3)
2064 char *s, *a0, *a1, *a2, *a3;
2070 sprintf(buf, s, a0, a1, a2, a3);
2073 fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
2074 buf, tok_print(yychar));
2075 fprintf(stderr, "%s\n", cur_line);
2076 printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
2077 buf, tok_print(yychar));
2081 yywarning(s, a0, a1, a2, a3)
2082 char *s, *a0, *a1, *a2, *a3;
2088 sprintf(buf, s, a0, a1, a2, a3);
2091 fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
2092 buf, tok_print(yychar));
2093 fprintf(stderr, "%s\n", cur_line);
2094 printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
2095 buf, tok_print(yychar));
2102 static char buf[1024];
2110 if(buf[p - 1] == '\n')