carl9170 firmware: fix [-Wpacked-not-aligned] warnings
[linux-libre-firmware.git] / as31 / as31 / parser.y
1 /* ----------------------------------------------------------------------
2  * FILE: parser.y
3  * PACKAGE: as31 - 8031/8051 Assembler.
4  *
5  * DESCRIPTION:
6  *      This file contains the yacc parser for the assembler.
7  *      Related to this are the following:
8  *              error(), warn(), yyerror()
9  *              genbyte(), genword(), genstr(), makeop()
10  *
11  *
12  * REVISION HISTORY:
13  *      Jan. 19, 1990 - Created. (Ken Stauffer)
14  *
15  * AUTHOR:
16  *      All code in this file written by Ken Stauffer (University of Calgary).
17  *      January 1990.
18  *
19  */
20
21 %{
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #define NOPE
27 #include "as31.h"
28 #undef NOPE
29
30 #define YYSTYPE union ystack
31
32 static unsigned char bytebuf[1024];             /* used by dumplist() */
33 static int bytecount;
34
35
36 void yyerror(const char *s);
37 int makeop(struct opcode * op, struct mode *m, int add);
38 void inclc(int i);
39 char *padline(char *line);
40 void dumplist(char *txt, int show);
41 void genbyte(int b);
42 void genstr(const char *s);
43 void genword(unsigned long w);
44
45 /* ------------------------ G R A M M E R ----------------------------- */
46
47 %}
48
49 %token STRING
50 %token D_ORG
51 %token D_BYTE
52 %token D_WORD
53 %token D_SKIP
54 %token D_EQU
55 %token D_FLAG
56 %token D_END
57 %token ACALL
58 %token ADD
59 %token ADDC
60 %token AJMP
61 %token ANL
62 %token CJNE
63 %token CLR
64 %token CPL
65 %token DA
66 %token DEC
67 %token DIV
68 %token DJNZ
69 %token INC
70 %token JB
71 %token JBC
72 %token JC
73 %token JMP
74 %token JNB
75 %token JNC
76 %token JNZ
77 %token JZ
78 %token LCALL
79 %token LJMP
80 %token MOV
81 %token MOVC
82 %token MOVX
83 %token NOP
84 %token MUL
85 %token ORL
86 %token POP
87 %token PUSH
88 %token RET
89 %token RETI
90 %token RL
91 %token RLC
92 %token RR
93 %token RRC
94 %token SETB
95 %token SJMP
96 %token SUBB
97 %token SWAP
98 %token XCH
99 %token XCHD
100 %token XRL
101 %token AB
102 %token A
103 %token C
104 %token PC
105 %token DPTR
106 %token BITPOS
107 %token R0
108 %token R1
109 %token R2
110 %token R3
111 %token R4
112 %token R5
113 %token R6
114 %token R7
115 %token VALUE
116 %token SYMBOL
117
118 %left '+' '-'
119 %left '*' '/' '%'
120 %left '|' '&'
121 %left '>' '<'
122
123 %start program
124
125 %%
126 program         :       linelist
127 {
128 }
129                 ;
130
131 linelist        : linelist line
132                 | line
133                 ;
134
135 line            : undefsym ':' linerest
136 {
137         if (abort_asap) {YYABORT;}
138         if( pass1 ) {
139                 $1.sym->type = LABEL;
140                 $1.sym->value = lc;
141         }
142         inclc($3.value);
143         bytecount = 0;
144 }
145                 | linerest              { inclc($1.value); bytecount = 0; }
146                 ;
147
148 linerest        : directive '\n'        {
149                                                 $$.value = $1.value;
150                                                 if( dashl && pass2 )
151                                                         dumplist($2.str,1);
152                                         }
153                 | instr '\n'            {
154                                                 $$.value = $1.value;
155                                                 if( dashl && pass2 )
156                                                         dumplist($2.str,1);
157
158                                         }
159                 | '\n'                  {
160                                                 $$.value = 0;
161                                                 if( dashl && pass2 )
162                                                         dumplist($1.str,0);
163                                         }
164                 | error                 {
165                                                 seek_eol();
166                                         }
167                    '\n'                 {
168                                                 $$.value = 0;
169                                                 if( dashl && pass2 )
170                                                         dumplist($1.str,0);
171                                         }
172                 ;
173
174
175
176
177
178 /* --------------------
179  * DIRECTIVES:
180  *
181  */
182
183 directive       : '.' D_ORG defexpr
184 {
185         lc = $3.val.v;
186         if( pass2 ) emitaddr(lc);
187         bytecount = 0;
188         $$.value = 0;
189 }
190                 | '.' D_BYTE blist      { $$.value = $3.value; }
191                 | '.' D_WORD wlist      { $$.value = $3.value; }
192                 | '.' D_SKIP defexpr    { $$.value = $3.val.v;
193                                           if( pass2 )
194                                                 emitaddr(lc+$$.value); }
195                 | '.' D_EQU undefsym ',' expr
196 {
197         if( $5.val.d == 0 )
198                 warn("Expression is undefined in pass 1");
199         $3.sym->type = LABEL;
200         $3.sym->value = $5.val.v;
201         $$.value = 0;
202 }
203         
204                 | '.' D_FLAG SYMBOL ',' flag
205 {
206         $3.sym->type = LABEL;
207         $3.sym->value = $5.value;
208         $$.value = 0;
209 }
210                 | '.' D_END                     { $$.value = 0; }
211                 ;
212
213 defexpr         : expr
214 {
215                 if( $1.val.d == 0 )
216                         warn("Expression is undefined in pass 1");
217                 if( !(isbit16($1.val.v)) )
218                         warn("Value greater than 16-bits");
219                 $$.value = $1.val.v;
220 }
221                 ;
222
223 flag            : flagv BITPOS
224 {
225         if( !isbit8($1.value) )
226                 warn("Bit address exceeds 8-bits");
227         if( isbmram($1.value) )
228                 $$.value = ($1.value-0x20)*8+ $2.value;
229         else if( isbmsfr($1.value) )
230                 $$.value = $1.value + $2.value;
231         else
232                 warn("Invalid bit addressable RAM location");
233 }
234                 ;
235
236 flagv           : SYMBOL
237 {
238         if( $1.sym->type == UNDEF )
239                 warn("Symbol %s must be defined in pass 1",$1.sym->name);
240         $$.value = $1.sym->value;
241 }
242                 | VALUE                 { $$.value = $1.value; }
243                 ;
244
245
246 undefsym        : SYMBOL
247 {
248         if( $1.sym->type != UNDEF && pass1)
249                 warn("Attempt to redefine symbol: %s",$1.sym->name);
250         $$.sym = $1.sym;
251 }
252                 ;
253
254 blist           : blist ',' data8
255 {
256         if( pass2 ) genbyte($3.value);
257         $$.value = $1.value + 1;
258 }
259                 | blist ',' STRING
260 {
261         if( pass1 )
262                 $$.value = $1.value + $3.value;
263         else {
264                 $$.value = $1.value + strlen($3.str);
265                 genstr($3.str);
266                 
267                 free($3.str);
268         }
269 }
270                 | data8
271 {
272         if( pass2 ) genbyte($1.value);
273         $$.value = 1;
274 }
275                 | STRING
276 {
277         if( pass1 )
278                 $$.value = $1.value;
279         else {
280                 $$.value = strlen($1.str);
281                 genstr($1.str);
282                 free($1.str);
283         }
284 }
285                 ;
286
287 wlist           : wlist ',' data16
288 {
289         if( pass2 ) genword($3.value);
290         $$.value = $1.value + 2;
291 }
292                 | data16
293 {
294         if( pass2 ) genword($1.value);
295         $$.value = 2;
296 }
297                 ;
298
299
300
301 /* --------------------
302  * EXPRESSIONS:
303  *
304  */
305
306 expr            : '*'                   { $$.val.v = lc;
307                                           $$.val.d = 1; }
308
309                 | '(' expr ')'          { $$.val.v = $2.val.v;
310                                           $$.val.d = $2.val.d; }
311
312                 | '-' expr %prec '*'    { $$.val.v = -$2.val.v;
313                                           $$.val.d = $2.val.d;  }
314
315                 | expr '|' expr         { $$.val.v = $1.val.v | $3.val.v;
316                                           $$.val.d = $1.val.d && $3.val.d; }
317
318                 | expr '&' expr         { $$.val.v = $1.val.v & $3.val.v;
319                                           $$.val.d = $1.val.d && $3.val.d; }
320
321                 | expr '*' expr         { $$.val.v = $1.val.v * $3.val.v;
322                                           $$.val.d = $1.val.d && $3.val.d; }
323
324                 | expr '/' expr         { $$.val.v = $1.val.v / $3.val.v;
325                                           $$.val.d = $1.val.d && $3.val.d; }
326
327                 | expr '%' expr         { $$.val.v = $1.val.v % $3.val.v;
328                                           $$.val.d = $1.val.d && $3.val.d; }
329
330                 | expr '-' expr         { $$.val.v = $1.val.v - $3.val.v;
331                                           $$.val.d = $1.val.d && $3.val.d; }
332
333                 | expr '+' expr         { $$.val.v = $1.val.v + $3.val.v;
334                                           $$.val.d = $1.val.d && $3.val.d; }
335
336                 | expr '>' '>' expr     { $$.val.v = $1.val.v >> $4.val.v;
337                                           $$.val.d = $1.val.d && $4.val.d; }
338
339                 | expr '<' '<' expr     { $$.val.v = $1.val.v << $4.val.v;
340                                           $$.val.d = $1.val.d && $4.val.d; }
341                 | SYMBOL
342 {
343         if( pass1 ) {
344                 $$.val.v = $1.sym->value;
345                 $$.val.d = ($1.sym->type != UNDEF);
346         }
347         else {
348                 if( $1.sym->type == UNDEF )
349                         warn("Undefined symbol %s",$1.sym->name);
350                 $$.val.v = $1.sym->value;
351                 $$.val.d = 1;
352         }
353 }
354                 | VALUE         { $$.val.v = $1.val.v; $$.val.d=1; }
355                 ;
356
357
358
359
360
361 /* --------------------
362  * INSTRUCTIONS:
363  *
364  */
365
366 instr           : NOP
367                                 { $$.value = makeop($1.op,NULL,0); }
368                 | ACALL addr11
369                                 { $$.value = makeop($1.op,&$2.mode,0); }
370                 | AJMP addr11
371                                 { $$.value = makeop($1.op,&$2.mode,0); }
372                 | ADD two_op1
373                                 { $$.value = makeop($1.op,&$2.mode,0); }
374                 | ADDC two_op1
375                                 { $$.value = makeop($1.op,&$2.mode,0); }
376                 | SUBB two_op1
377                                 { $$.value = makeop($1.op,&$2.mode,0); }
378                 | XRL two_op1
379                                 { $$.value = makeop($1.op,&$2.mode,0); }
380                 | XRL two_op2
381                                 { $$.value = makeop($1.op,&$2.mode,4); }
382                 | ANL two_op1
383                                 { $$.value = makeop($1.op,&$2.mode,0); }
384                 | ANL two_op2
385                                 { $$.value = makeop($1.op,&$2.mode,4); }
386                 | ANL two_op3
387                                 { $$.value = makeop($1.op,&$2.mode,6); }
388                 | ORL two_op1
389                                 { $$.value = makeop($1.op,&$2.mode,0); }
390                 | ORL two_op2
391                                 { $$.value = makeop($1.op,&$2.mode,4); }
392                 | ORL two_op3
393                                 { $$.value = makeop($1.op,&$2.mode,6); }
394                 | XCH two_op1
395                                 { if( get_md($2.mode) == 3 )
396                                         warn("Immediate mode is illegal");
397                                   $$.value = makeop($1.op,&$2.mode,0);
398                                 }
399                 | INC single_op1
400                                 { $$.value = makeop($1.op,&$2.mode,0); }
401                 | INC DPTR
402                                 { $$.value = makeop($1.op,NULL,4); }
403                 | DEC single_op1
404                                 { $$.value = makeop($1.op,&$2.mode,0); }
405                 | DA A
406                                 { $$.value = makeop($1.op,NULL,0); }
407                 | DIV AB
408                                 { $$.value = makeop($1.op,NULL,0); }
409                 | JMP '@' A '+' DPTR
410                                 { $$.value = makeop($1.op,NULL,0); }
411                 | JMP '@' DPTR '+' A
412                                 { $$.value = makeop($1.op,NULL,0); }
413                 | MUL AB
414                                 { $$.value = makeop($1.op,NULL,0); }
415                 | RET
416                                 { $$.value = makeop($1.op,NULL,0); }
417                 | RETI
418                                 { $$.value = makeop($1.op,NULL,0); }
419                 | RL A
420                                 { $$.value = makeop($1.op,NULL,0); }
421                 | RLC A
422                                 { $$.value = makeop($1.op,NULL,0); }
423                 | RR A
424                                 { $$.value = makeop($1.op,NULL,0); }
425                 | RRC A
426                                 { $$.value = makeop($1.op,NULL,0); }
427                 | SWAP A
428                                 { $$.value = makeop($1.op,NULL,0); }
429                 | XCHD two_op1
430                                 { if( get_md($2.mode) != 2 )
431                                         warn("Invalid addressing mode");
432                                   $$.value = makeop($1.op,&$2.mode,-2); }
433                 | CLR single_op2
434                                 { $$.value = makeop($1.op,&$2.mode,0); }
435                 | CPL single_op2
436                                 { $$.value = makeop($1.op,&$2.mode,0); }
437                 | SETB single_op2
438                                 { if( get_md($2.mode) == 0 )
439                                         warn("Invalid addressing mode");
440                                   $$.value = makeop($1.op,&$2.mode,-1); }
441                 | PUSH data8
442                                 {
443                                    struct mode tmp;
444                                         set_md(tmp,0);
445                                         set_ov(tmp,0);
446                                         set_sz(tmp,1);
447                                         set_b1(tmp,$2.value);
448                                         $$.value = makeop($1.op,&tmp,0);
449                                 }
450                 | POP data8
451                                 {
452                                    struct mode tmp;
453                                         set_md(tmp,0);
454                                         set_ov(tmp,0);
455                                         set_sz(tmp,1);
456                                         set_b1(tmp,$2.value);
457                                         $$.value = makeop($1.op,&tmp,0);
458                                 }
459                 | LJMP addr16
460                                 { $$.value = makeop($1.op,&$2.mode,0); }
461                 | LCALL addr16
462                                 { $$.value = makeop($1.op,&$2.mode,0); }
463                 | JC relative
464                                 { $$.value = makeop($1.op,&$2.mode,0); }
465                 | JNC relative
466                                 { $$.value = makeop($1.op,&$2.mode,0); }
467                 | JNZ relative
468                                 { $$.value = makeop($1.op,&$2.mode,0); }
469                 | JZ relative
470                                 { $$.value = makeop($1.op,&$2.mode,0); }
471                 | SJMP relative
472                                 { $$.value = makeop($1.op,&$2.mode,0); }
473                 | CJNE three_op1
474                                 { $$.value = makeop($1.op,&$2.mode,0); }
475                 | JB two_op4
476                                 { $$.value = makeop($1.op,&$2.mode,0); }
477                 | JNB two_op4
478                                 { $$.value = makeop($1.op,&$2.mode,0); }
479                 | JBC two_op4
480                                 { $$.value = makeop($1.op,&$2.mode,0); }
481                 | DJNZ two_op5
482                                 { $$.value = makeop($1.op,&$2.mode,0); }
483                 | MOV two_op1
484                                 { $$.value = makeop($1.op,&$2.mode,0); }
485                 | MOV two_op2
486                                 { $$.value = makeop($1.op,&$2.mode,4); }
487                 | MOV two_op6
488                                 { $$.value = makeop($1.op,&$2.mode,6); }
489
490
491                 | MOVC A ',' '@' A '+' DPTR
492                                 { $$.value = makeop($1.op,NULL,0); }
493                 | MOVC A ',' '@' DPTR '+' A
494                                 { $$.value = makeop($1.op,NULL,0); }
495                 | MOVC A ',' '@' A '+' PC
496                                 { $$.value = makeop($1.op,NULL,1); }
497                 | MOVC A ',' '@' PC '+' A
498                                 { $$.value = makeop($1.op,NULL,1); }
499
500                 | MOVX A ',' '@' regi
501                                 { $$.value = makeop($1.op,NULL,$5.value); }
502                 | MOVX A ',' '@' DPTR
503                                 { $$.value = makeop($1.op,NULL,2); }
504                 | MOVX '@' regi ',' A
505                                 { $$.value = makeop($1.op,NULL,$3.value+3); }
506                 | MOVX '@' DPTR ',' A
507                                 { $$.value = makeop($1.op,NULL,5); }
508                 ;
509
510
511
512
513 /* --------------------
514  * ADDRESSING MODES:
515  *
516  */
517
518 two_op1         : A ',' reg
519                                 {
520                                         set_md($$.mode,0);
521                                         set_ov($$.mode, $3.value);
522                                         set_sz($$.mode, 0);
523                                 }
524                 | A ',' data8
525                                 {
526                                         set_md($$.mode,1);
527                                         set_ov($$.mode,0);
528                                         set_sz($$.mode,1);
529                                         set_b1($$.mode,$3.value);
530                                 }
531                 | A ',' '@' regi
532                                 {
533                                         set_md($$.mode,2);
534                                         set_ov($$.mode,$4.value);
535                                         set_sz($$.mode,0);
536                                 }
537                 | A ',' '#' data8
538                                 {
539                                         set_md($$.mode,3);
540                                         set_ov($$.mode,0);
541                                         set_sz($$.mode,1);
542                                         set_b1($$.mode,$4.value);
543                                 }
544                 ;
545
546 two_op2         : data8 ',' A
547                                 {
548                                         set_md($$.mode,0);
549                                         set_ov($$.mode,0);
550                                         set_sz($$.mode,1);
551                                         set_b1($$.mode,$1.value);
552                                 }
553                 | data8 ',' '#' data8
554                                 {
555                                         set_md($$.mode,1);
556                                         set_ov($$.mode,0);
557                                         set_sz($$.mode,2);
558                                         set_b1($$.mode,$1.value);
559                                         set_b2($$.mode,$4.value);
560                                 }
561                 ;
562
563 two_op3         : C ',' bit
564                                 {
565                                         set_md($$.mode,0);
566                                         set_ov($$.mode,0);
567                                         set_sz($$.mode,1);
568                                         set_b1($$.mode,$3.value);
569                                 }
570                 | C ',' '/' bit
571                                 {
572                                         set_md($$.mode,1);
573                                         set_ov($$.mode,0);
574                                         set_sz($$.mode,1);
575                                         set_b1($$.mode,$4.value);
576                                 }
577                 | C ',' '!' bit
578                                 {
579                                         set_md($$.mode,1);
580                                         set_ov($$.mode,0);
581                                         set_sz($$.mode,1);
582                                         set_b1($$.mode,$4.value);
583                                 }
584                 ;
585
586 two_op4         : bit ',' rel
587                                 {
588                                         set_md($$.mode,0);
589                                         set_ov($$.mode,0);
590                                         set_sz($$.mode,2);
591                                         set_b1($$.mode,$1.value);
592                                         set_b2($$.mode,$3.value);
593                                 }
594                 ;
595
596 two_op5         : reg ',' rel2
597                                 {
598                                         set_md($$.mode,0);
599                                         set_ov($$.mode,$1.value);
600                                         set_sz($$.mode,1);
601                                         set_b1($$.mode,$3.value);
602                                 }
603                 | data8 ',' rel
604                                 {
605                                         set_md($$.mode,1);
606                                         set_ov($$.mode,0);
607                                         set_sz($$.mode,2);
608                                         set_b1($$.mode,$1.value);
609                                         set_b2($$.mode,$3.value);
610                                 }
611                 ;
612
613 two_op6         : reg ',' A
614                                 {
615                                         set_md($$.mode,0);
616                                         set_ov($$.mode,$1.value);
617                                         set_sz($$.mode,0);
618                                 }
619                 | reg ',' data8
620                                 {
621                                         set_md($$.mode,1);
622                                         set_ov($$.mode,$1.value);
623                                         set_sz($$.mode,1);
624                                         set_b1($$.mode,$3.value);
625                                 }
626                 | reg ',' '#' data8
627                                 {
628                                         set_md($$.mode,2);
629                                         set_ov($$.mode,$1.value);
630                                         set_sz($$.mode,1);
631                                         set_b1($$.mode,$4.value);
632                                 }
633                 | data8 ',' reg
634                                 {
635                                         set_md($$.mode,3);
636                                         set_ov($$.mode,$3.value);
637                                         set_sz($$.mode,1);
638                                         set_b1($$.mode,$1.value);
639                                 }
640                 | data8 ',' data8
641                                 {
642                                         set_md($$.mode,4);
643                                         set_ov($$.mode,0);
644                                         set_sz($$.mode,2);
645                                         set_b1($$.mode,$3.value);
646                                         set_b2($$.mode,$1.value);
647                                 }
648                 | data8 ',' '@' regi
649                                 {
650                                         set_md($$.mode,5);
651                                         set_ov($$.mode,$4.value);
652                                         set_sz($$.mode,1);
653                                         set_b1($$.mode,$1.value);
654                                 }
655                 | '@' regi ',' A
656                                 {
657                                         set_md($$.mode,6);
658                                         set_ov($$.mode,$2.value);
659                                         set_sz($$.mode,0);
660                                 }
661                 | '@' regi ',' data8
662                                 {
663                                         set_md($$.mode,7);
664                                         set_ov($$.mode,$2.value);
665                                         set_sz($$.mode,1);
666                                         set_b1($$.mode,$4.value);
667                                 }
668                 | '@' regi ',' '#' data8
669                                 {
670                                         set_md($$.mode,8);
671                                         set_ov($$.mode,$2.value);
672                                         set_sz($$.mode,1);
673                                         set_b1($$.mode,$5.value);
674                                 }
675                 | DPTR ',' '#' data16
676                         {
677                                 set_md($$.mode,9);
678                                 set_ov($$.mode,0);
679                                 set_sz($$.mode,2);
680                                 set_b1($$.mode, ($4.value & 0xff00) >> 8 );
681                                 set_b2($$.mode, ($4.value & 0x00ff) );
682                         }
683                 | C ',' bit
684                                 {
685                                         set_md($$.mode,10);
686                                         set_ov($$.mode,0);
687                                         set_sz($$.mode,1);
688                                         set_b1($$.mode,$3.value);
689                                 }
690         /*
691          * Following two productions cannot be represented by:
692          *
693          *      bit ',' C
694          *
695          * Because yacc gives tons of reduce/reduce errors if
696          * that is attempted.
697          *
698          */
699                 | data8 ',' C
700                                 {
701                                         set_md($$.mode,11);
702                                         set_ov($$.mode,0);
703                                         set_sz($$.mode,1);
704                                         set_b1($$.mode,$1.value);
705                                 }
706                 | data8 BITPOS ',' C
707 {
708         if( pass2 ) {
709                 if( !isbit8($1.value) )
710                         warn("Bit address exceeds 8-bits");
711                 if( isbmram($1.value) )
712                         set_b1($$.mode, ($1.value-0x20)*8+ $2.value );
713                 else if( isbmsfr($1.value) )
714                         set_b1($$.mode, $1.value + $2.value );
715                 else
716                         warn("Invalid bit addressable RAM location");
717         }
718         set_md($$.mode,11);
719         set_ov($$.mode,0);
720         set_sz($$.mode,1);
721 }
722                 ;
723
724
725 single_op1      : A
726                                 {
727                                         set_md($$.mode,0);
728                                         set_ov($$.mode,0);
729                                         set_sz($$.mode,0);
730                                 }
731
732                 | reg
733                                 {
734                                         set_md($$.mode,1);
735                                         set_ov($$.mode,$1.value);
736                                         set_sz($$.mode,0);
737                                 }
738                 | data8
739                                 {
740                                         set_md($$.mode,2);
741                                         set_ov($$.mode,0);
742                                         set_sz($$.mode,1);
743                                         set_b1($$.mode,$1.value);
744                                 }
745                 | '@' regi
746                                 {
747                                         set_md($$.mode,3);
748                                         set_ov($$.mode,$2.value);
749                                         set_sz($$.mode,0);
750                                 }
751                 ;
752
753 single_op2      : A
754                                 {
755                                         set_md($$.mode,0);
756                                         set_ov($$.mode,0);
757                                         set_sz($$.mode,0);
758                                 }
759                 | C
760                                 {
761                                         set_md($$.mode,1);
762                                         set_ov($$.mode,0);
763                                         set_sz($$.mode,0);
764                                 }
765                 | bit
766                                 {
767                                         set_md($$.mode,2);
768                                         set_ov($$.mode,0);
769                                         set_sz($$.mode,1);
770                                         set_b1($$.mode,$1.value);
771                                 }
772                 ;
773
774 three_op1       : A ',' data8 ',' rel
775                                 {
776                                         set_md($$.mode,0);
777                                         set_ov($$.mode,0);
778                                         set_sz($$.mode,2);
779                                         set_b1($$.mode,$3.value);
780                                         set_b2($$.mode,$5.value);
781                                 }
782                 | A ',' '#' data8 ',' rel
783                                 {
784                                         set_md($$.mode,1);
785                                         set_ov($$.mode,0);
786                                         set_sz($$.mode,2);
787                                         set_b1($$.mode,$4.value);
788                                         set_b2($$.mode,$6.value);
789                                 }
790                 | reg ',' '#' data8 ',' rel
791                                 {
792                                         set_md($$.mode,2);
793                                         set_ov($$.mode,$1.value);
794                                         set_sz($$.mode,2);
795                                         set_b1($$.mode,$4.value);
796                                         set_b2($$.mode,$6.value);
797                                 }
798                 | '@' regi ',' '#' data8 ',' rel
799                                 {
800                                         set_md($$.mode,3);
801                                         set_ov($$.mode,$2.value);
802                                         set_sz($$.mode,2);
803                                         set_b1($$.mode,$5.value);
804                                         set_b2($$.mode,$7.value);
805                                 }
806                 ;
807
808 rel             : expr
809 {
810                 long offset;
811                 if( pass2 ) {
812                         offset = $1.val.v - (lc+3);
813                         if( offset > 127 || offset < -128 )
814                            warn("Relative offset exceeds -128 / +127");
815                         $$.value = offset;
816                 }
817 }
818                 ;
819
820 /*
821  * This production differs from the above, by 1 number!
822  *
823  */
824
825 rel2            : expr
826 {
827                 long offset;
828                 if( pass2 ) {
829                         offset = $1.val.v - (lc+2); /* different! */
830                         if( offset > 127 || offset < -128 )
831                            warn("Relative offset exceeds -128 / +127");
832                         $$.value = offset;
833                 }
834 }
835                 ;
836
837
838 bit             : bitv BITPOS
839 {
840         if( pass2 ) {
841                 if( !isbit8($1.value) )
842                         warn("Bit address exceeds 8-bits");
843                 if( isbmram($1.value) )
844                         $$.value = ($1.value-0x20)*8+$2.value;
845                 else if( isbmsfr($1.value) )
846                         $$.value = $1.value + $2.value;
847                 else
848                         warn("Invalid bit addressable RAM location");
849         }
850 }
851                 | bitv
852 {
853         if( pass2 ) {
854                 if( !isbit8($1.value) )
855                         warn("Bit address exceeds 8-bits");
856                 $$.value = $1.value;
857         }
858 }
859                 ;
860
861 bitv            : SYMBOL
862 {
863         if( $1.sym->type == UNDEF && pass2 )
864                 warn("Symbol %s undefined",$1.sym->name);
865         $$.value = $1.sym->value;
866 }
867                 | VALUE         { $$.value = $1.value; }
868                 ;
869
870 reg             : R0            { $$.value = 0; }
871                 | R1            { $$.value = 1; }
872                 | R2            { $$.value = 2; }
873                 | R3            { $$.value = 3; }
874                 | R4            { $$.value = 4; }
875                 | R5            { $$.value = 5; }
876                 | R6            { $$.value = 6; }
877                 | R7            { $$.value = 7; }
878                 ;
879
880 regi            : R0            { $$.value = 0; }
881                 | R1            { $$.value = 1; }
882                 | R2
883                                 { $$.value = 0;
884                                   warn("Illegal indirect register: @r2"); }
885                 | R3
886                                 { $$.value = 0;
887                                   warn("Illegal indirect register: @r3"); }
888                 | R4
889                                 { $$.value = 0;
890                                   warn("Illegal indirect register: @r4"); }
891                 | R5
892                                 { $$.value = 0;
893                                   warn("Illegal indirect register: @r5"); }
894                 | R6
895                                 { $$.value = 0;
896                                   warn("Illegal indirect register: @r6"); }
897                 | R7
898                                 { $$.value = 0;
899                                   warn("Illegal indirect register: @r7"); }
900                 ;
901
902 data8           : expr
903 {
904         if( pass2 ) {
905                 if( !isbit8($1.val.v) )
906                         warn("Expression greater than 8-bits");
907         }
908         $$.value = $1.val.v;
909 }
910                 ;
911
912 data16          : expr
913 {
914         if( pass2 ) {
915                 if( !isbit16($1.val.v) )
916                         warn("Expression greater than 16-bits");
917         }
918         $$.value = $1.val.v;
919 }
920                 ;
921
922 addr11          : expr
923 {
924                 if( pass2 ) {
925                         if( !isbit16($1.val.v)  )
926                                 warn("Address greater than 16-bits");
927                         if( ($1.val.v & size11) != ((lc+2) & size11) )
928                                 warn("Address outside current 2K page");
929                 }
930                 set_md($$.mode,0);
931                 set_ov($$.mode, ($1.val.v&0x0700)>>3 );
932                 set_sz($$.mode,1);
933                 set_b1($$.mode,$1.val.v&0x00ff);
934 }
935                 ;
936
937 addr16          : expr
938 {
939                 if( pass2 ) {
940                         if( !isbit16($1.val.v)  )
941                                 warn("Address greater than 16-bits");
942                 }
943                 set_md($$.mode,0);
944                 set_ov($$.mode, 0 );
945                 set_sz($$.mode,2);
946                 set_b1($$.mode, ($1.val.v & 0xff00 ) >> 8 );
947                 set_b2($$.mode, ($1.val.v & 0x00ff ) );
948 }
949                 ;
950
951 relative        : expr
952 {
953                 long offset=0;
954                 if( pass2 ) {
955                         offset = $1.val.v - (lc+2);
956                         if( offset>127 || offset<-128 )
957                            warn("Relative offset exceeds -128 / +127");
958                 }
959                 set_md($$.mode,0);
960                 set_ov($$.mode,0);
961                 set_sz($$.mode,1);
962                 set_b1($$.mode,offset);
963
964 }
965                 ;
966
967 %%
968
969 /* ---------------------------------------------------------------------- */
970
971 void yyerror(const char *s)
972 {
973         warn("%s near \"%s\"", s, get_last_token());
974 }
975
976
977 /* ----------------------------------------------------------------------
978  * makeop:
979  *      This function makes an opcode based on the instruction symbol table
980  *      entry, and an addressing mode structure.
981  *      This function is called from both passes, but
982  *      only generates code in pass 2.
983  *
984  *      Resultant opcode bytes are passed to genbyte().
985  *
986  *      Returns the nuumber of bytes that the instruction
987  *      occupies.
988  *
989  */
990
991 int makeop(struct opcode * op, struct mode *m, int add)
992 {
993         register unsigned int newop;
994
995         if( m == NULL ) {
996                 if(pass2) genbyte(op->bytes[0+add]);
997                 return(1);
998         }
999
1000         if( pass2 ) {
1001                 newop = op->bytes[ get_md(*m)+add ] | get_ov(*m);
1002                 genbyte(newop);
1003                 if( get_sz(*m) > 0 ) genbyte( get_b1(*m) );
1004                 if( get_sz(*m) > 1 ) genbyte( get_b2(*m) );
1005         }
1006         return( get_sz(*m)+1 );
1007 }
1008
1009
1010 /* ----------------------------------------------------------------------
1011  * inclc:
1012  *      Increments the Location Counter by 'i' amount.
1013  *      Check to see if 'i' overflows 64K.
1014  *      Checks to see if assembler is overlapping previous sections
1015  *      of code. (using a large bit field).
1016  *
1017  */
1018
1019 #define indx(a) ( (a)/(32) )
1020 #define bit(a)  ( 1 << ((a)%(32)) )
1021
1022 #define getloc(a) (regions[indx(a)] & bit(a))
1023 #define setloc(a) (regions[indx(a)] |= bit(a))
1024
1025 static unsigned long regions[ 0x10000/(32) ];
1026
1027 void inclc(int i)
1028 {
1029
1030         while (i-- > 0) {
1031                 if( pass2 && getloc(lc) )
1032                         error("Location counter overlaps");
1033                 if( pass2 ) setloc(lc);
1034                 lc += 1;
1035         }
1036                 
1037         if( lc > 0xffff )
1038                 error("Location counter has exceeded 16-bits");
1039 }
1040
1041 void clear_location_counter(void)
1042 {
1043         memset(regions, 0, sizeof(regions));
1044 }
1045
1046
1047 /* ----------------------------------------------------------------------
1048  * padline:
1049  *      This routine returns a new string, which is equivilant to
1050  *      'line' except that all tabs have been expanded to spaces, and
1051  *      the total length has been truncated to 60 chars.
1052  */
1053
1054 char *padline(char *line)
1055 {
1056         static char newline[61];
1057         char *p1;
1058         int pos=0,nxtpos;
1059
1060         for(p1=line; pos<sizeof(newline)-1 && *p1; p1++ ) {
1061                 if( *p1 == '\t' ) {
1062                         nxtpos = pos+8-pos%8;
1063                         while(pos<sizeof(newline)-1 && pos <= nxtpos)
1064                                 newline[pos++] = ' ';
1065                 } else if( *p1 != '\n' )
1066                         newline[pos++]= *p1;
1067         }
1068         newline[pos] = '\0';
1069         return(newline);
1070 }
1071
1072
1073 /* ----------------------------------------------------------------------
1074  * dumplist:
1075  *      Outputs the current location counter, bytebuf[] array, and
1076  *      the string 'txt' to the listing file.
1077  *      This routine is called for every source line encountered in the
1078  *      source file. (Only in pass 2, and if listing is turned on).
1079  *
1080  */
1081
1082 void dumplist(char *txt, int show)
1083 {
1084         int i,j;
1085
1086         fprintf(listing,show?"%04lX: ":"      ",lc);
1087
1088         j=0;
1089         for(i=0; i<bytecount; i++ ) {
1090                 fprintf(listing,"%02X ",bytebuf[i]);
1091                 if( ++j >= 4 ) {
1092                         j = 0;
1093                         fprintf(listing,"\n      ");
1094                 }
1095         }
1096         while(++j <= 4)
1097                 fprintf(listing,"   ");
1098
1099         fprintf(listing," %s\n",padline(txt));
1100 }
1101
1102 /* ----------------------------------------------------------------------
1103  * gen* routines:
1104  *      Place information into the bytebuf[] array, and also
1105  *      call emitbyte with the byte.
1106  *
1107  */
1108
1109 void genbyte(int b)
1110 {
1111         if( bytecount < sizeof(bytebuf) )
1112                 bytebuf[bytecount++] = b;
1113         emitbyte(b);
1114 }
1115
1116 void genstr(const char *s)
1117 {
1118         while( *s )
1119                 genbyte(*s++);
1120 }
1121
1122 void genword(unsigned long w)
1123 {
1124         genbyte( (w & 0xff00) >> 8 );
1125         genbyte( (w & 0x00ff) );
1126 }
1127