1 /* ----------------------------------------------------------------------
3 * PACKAGE: as31 - 8031/8051 Assembler.
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()
13 * Jan. 19, 1990 - Created. (Ken Stauffer)
16 * All code in this file written by Ken Stauffer (University of Calgary).
30 #define YYSTYPE union ystack
32 static unsigned char bytebuf[1024]; /* used by dumplist() */
36 void yyerror(const char *s);
37 int makeop(struct opcode * op, struct mode *m, int add);
39 char *padline(char *line);
40 void dumplist(char *txt, int show);
42 void genstr(const char *s);
43 void genword(unsigned long w);
45 /* ------------------------ G R A M M E R ----------------------------- */
131 linelist : linelist line
135 line : undefsym ':' linerest
137 if (abort_asap) {YYABORT;}
139 $1.sym->type = LABEL;
145 | linerest { inclc($1.value); bytecount = 0; }
148 linerest : directive '\n' {
178 /* --------------------
183 directive : '.' D_ORG defexpr
186 if( pass2 ) emitaddr(lc);
190 | '.' D_BYTE blist { $$.value = $3.value; }
191 | '.' D_WORD wlist { $$.value = $3.value; }
192 | '.' D_SKIP defexpr { $$.value = $3.val.v;
194 emitaddr(lc+$$.value); }
195 | '.' D_EQU undefsym ',' expr
198 warn("Expression is undefined in pass 1");
199 $3.sym->type = LABEL;
200 $3.sym->value = $5.val.v;
204 | '.' D_FLAG SYMBOL ',' flag
206 $3.sym->type = LABEL;
207 $3.sym->value = $5.value;
210 | '.' D_END { $$.value = 0; }
216 warn("Expression is undefined in pass 1");
217 if( !(isbit16($1.val.v)) )
218 warn("Value greater than 16-bits");
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;
232 warn("Invalid bit addressable RAM location");
238 if( $1.sym->type == UNDEF )
239 warn("Symbol %s must be defined in pass 1",$1.sym->name);
240 $$.value = $1.sym->value;
242 | VALUE { $$.value = $1.value; }
248 if( $1.sym->type != UNDEF && pass1)
249 warn("Attempt to redefine symbol: %s",$1.sym->name);
254 blist : blist ',' data8
256 if( pass2 ) genbyte($3.value);
257 $$.value = $1.value + 1;
262 $$.value = $1.value + $3.value;
264 $$.value = $1.value + strlen($3.str);
272 if( pass2 ) genbyte($1.value);
280 $$.value = strlen($1.str);
287 wlist : wlist ',' data16
289 if( pass2 ) genword($3.value);
290 $$.value = $1.value + 2;
294 if( pass2 ) genword($1.value);
301 /* --------------------
306 expr : '*' { $$.val.v = lc;
309 | '(' expr ')' { $$.val.v = $2.val.v;
310 $$.val.d = $2.val.d; }
312 | '-' expr %prec '*' { $$.val.v = -$2.val.v;
313 $$.val.d = $2.val.d; }
315 | expr '|' expr { $$.val.v = $1.val.v | $3.val.v;
316 $$.val.d = $1.val.d && $3.val.d; }
318 | expr '&' expr { $$.val.v = $1.val.v & $3.val.v;
319 $$.val.d = $1.val.d && $3.val.d; }
321 | expr '*' expr { $$.val.v = $1.val.v * $3.val.v;
322 $$.val.d = $1.val.d && $3.val.d; }
324 | expr '/' expr { $$.val.v = $1.val.v / $3.val.v;
325 $$.val.d = $1.val.d && $3.val.d; }
327 | expr '%' expr { $$.val.v = $1.val.v % $3.val.v;
328 $$.val.d = $1.val.d && $3.val.d; }
330 | expr '-' expr { $$.val.v = $1.val.v - $3.val.v;
331 $$.val.d = $1.val.d && $3.val.d; }
333 | expr '+' expr { $$.val.v = $1.val.v + $3.val.v;
334 $$.val.d = $1.val.d && $3.val.d; }
336 | expr '>' '>' expr { $$.val.v = $1.val.v >> $4.val.v;
337 $$.val.d = $1.val.d && $4.val.d; }
339 | expr '<' '<' expr { $$.val.v = $1.val.v << $4.val.v;
340 $$.val.d = $1.val.d && $4.val.d; }
344 $$.val.v = $1.sym->value;
345 $$.val.d = ($1.sym->type != UNDEF);
348 if( $1.sym->type == UNDEF )
349 warn("Undefined symbol %s",$1.sym->name);
350 $$.val.v = $1.sym->value;
354 | VALUE { $$.val.v = $1.val.v; $$.val.d=1; }
361 /* --------------------
367 { $$.value = makeop($1.op,NULL,0); }
369 { $$.value = makeop($1.op,&$2.mode,0); }
371 { $$.value = makeop($1.op,&$2.mode,0); }
373 { $$.value = makeop($1.op,&$2.mode,0); }
375 { $$.value = makeop($1.op,&$2.mode,0); }
377 { $$.value = makeop($1.op,&$2.mode,0); }
379 { $$.value = makeop($1.op,&$2.mode,0); }
381 { $$.value = makeop($1.op,&$2.mode,4); }
383 { $$.value = makeop($1.op,&$2.mode,0); }
385 { $$.value = makeop($1.op,&$2.mode,4); }
387 { $$.value = makeop($1.op,&$2.mode,6); }
389 { $$.value = makeop($1.op,&$2.mode,0); }
391 { $$.value = makeop($1.op,&$2.mode,4); }
393 { $$.value = makeop($1.op,&$2.mode,6); }
395 { if( get_md($2.mode) == 3 )
396 warn("Immediate mode is illegal");
397 $$.value = makeop($1.op,&$2.mode,0);
400 { $$.value = makeop($1.op,&$2.mode,0); }
402 { $$.value = makeop($1.op,NULL,4); }
404 { $$.value = makeop($1.op,&$2.mode,0); }
406 { $$.value = makeop($1.op,NULL,0); }
408 { $$.value = makeop($1.op,NULL,0); }
410 { $$.value = makeop($1.op,NULL,0); }
412 { $$.value = makeop($1.op,NULL,0); }
414 { $$.value = makeop($1.op,NULL,0); }
416 { $$.value = makeop($1.op,NULL,0); }
418 { $$.value = makeop($1.op,NULL,0); }
420 { $$.value = makeop($1.op,NULL,0); }
422 { $$.value = makeop($1.op,NULL,0); }
424 { $$.value = makeop($1.op,NULL,0); }
426 { $$.value = makeop($1.op,NULL,0); }
428 { $$.value = makeop($1.op,NULL,0); }
430 { if( get_md($2.mode) != 2 )
431 warn("Invalid addressing mode");
432 $$.value = makeop($1.op,&$2.mode,-2); }
434 { $$.value = makeop($1.op,&$2.mode,0); }
436 { $$.value = makeop($1.op,&$2.mode,0); }
438 { if( get_md($2.mode) == 0 )
439 warn("Invalid addressing mode");
440 $$.value = makeop($1.op,&$2.mode,-1); }
447 set_b1(tmp,$2.value);
448 $$.value = makeop($1.op,&tmp,0);
456 set_b1(tmp,$2.value);
457 $$.value = makeop($1.op,&tmp,0);
460 { $$.value = makeop($1.op,&$2.mode,0); }
462 { $$.value = makeop($1.op,&$2.mode,0); }
464 { $$.value = makeop($1.op,&$2.mode,0); }
466 { $$.value = makeop($1.op,&$2.mode,0); }
468 { $$.value = makeop($1.op,&$2.mode,0); }
470 { $$.value = makeop($1.op,&$2.mode,0); }
472 { $$.value = makeop($1.op,&$2.mode,0); }
474 { $$.value = makeop($1.op,&$2.mode,0); }
476 { $$.value = makeop($1.op,&$2.mode,0); }
478 { $$.value = makeop($1.op,&$2.mode,0); }
480 { $$.value = makeop($1.op,&$2.mode,0); }
482 { $$.value = makeop($1.op,&$2.mode,0); }
484 { $$.value = makeop($1.op,&$2.mode,0); }
486 { $$.value = makeop($1.op,&$2.mode,4); }
488 { $$.value = makeop($1.op,&$2.mode,6); }
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); }
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); }
513 /* --------------------
521 set_ov($$.mode, $3.value);
529 set_b1($$.mode,$3.value);
534 set_ov($$.mode,$4.value);
542 set_b1($$.mode,$4.value);
546 two_op2 : data8 ',' A
551 set_b1($$.mode,$1.value);
553 | data8 ',' '#' data8
558 set_b1($$.mode,$1.value);
559 set_b2($$.mode,$4.value);
568 set_b1($$.mode,$3.value);
575 set_b1($$.mode,$4.value);
582 set_b1($$.mode,$4.value);
586 two_op4 : bit ',' rel
591 set_b1($$.mode,$1.value);
592 set_b2($$.mode,$3.value);
596 two_op5 : reg ',' rel2
599 set_ov($$.mode,$1.value);
601 set_b1($$.mode,$3.value);
608 set_b1($$.mode,$1.value);
609 set_b2($$.mode,$3.value);
616 set_ov($$.mode,$1.value);
622 set_ov($$.mode,$1.value);
624 set_b1($$.mode,$3.value);
629 set_ov($$.mode,$1.value);
631 set_b1($$.mode,$4.value);
636 set_ov($$.mode,$3.value);
638 set_b1($$.mode,$1.value);
645 set_b1($$.mode,$3.value);
646 set_b2($$.mode,$1.value);
651 set_ov($$.mode,$4.value);
653 set_b1($$.mode,$1.value);
658 set_ov($$.mode,$2.value);
664 set_ov($$.mode,$2.value);
666 set_b1($$.mode,$4.value);
668 | '@' regi ',' '#' data8
671 set_ov($$.mode,$2.value);
673 set_b1($$.mode,$5.value);
675 | DPTR ',' '#' data16
680 set_b1($$.mode, ($4.value & 0xff00) >> 8 );
681 set_b2($$.mode, ($4.value & 0x00ff) );
688 set_b1($$.mode,$3.value);
691 * Following two productions cannot be represented by:
695 * Because yacc gives tons of reduce/reduce errors if
704 set_b1($$.mode,$1.value);
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 );
716 warn("Invalid bit addressable RAM location");
735 set_ov($$.mode,$1.value);
743 set_b1($$.mode,$1.value);
748 set_ov($$.mode,$2.value);
770 set_b1($$.mode,$1.value);
774 three_op1 : A ',' data8 ',' rel
779 set_b1($$.mode,$3.value);
780 set_b2($$.mode,$5.value);
782 | A ',' '#' data8 ',' rel
787 set_b1($$.mode,$4.value);
788 set_b2($$.mode,$6.value);
790 | reg ',' '#' data8 ',' rel
793 set_ov($$.mode,$1.value);
795 set_b1($$.mode,$4.value);
796 set_b2($$.mode,$6.value);
798 | '@' regi ',' '#' data8 ',' rel
801 set_ov($$.mode,$2.value);
803 set_b1($$.mode,$5.value);
804 set_b2($$.mode,$7.value);
812 offset = $1.val.v - (lc+3);
813 if( offset > 127 || offset < -128 )
814 warn("Relative offset exceeds -128 / +127");
821 * This production differs from the above, by 1 number!
829 offset = $1.val.v - (lc+2); /* different! */
830 if( offset > 127 || offset < -128 )
831 warn("Relative offset exceeds -128 / +127");
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;
848 warn("Invalid bit addressable RAM location");
854 if( !isbit8($1.value) )
855 warn("Bit address exceeds 8-bits");
863 if( $1.sym->type == UNDEF && pass2 )
864 warn("Symbol %s undefined",$1.sym->name);
865 $$.value = $1.sym->value;
867 | VALUE { $$.value = $1.value; }
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; }
880 regi : R0 { $$.value = 0; }
881 | R1 { $$.value = 1; }
884 warn("Illegal indirect register: @r2"); }
887 warn("Illegal indirect register: @r3"); }
890 warn("Illegal indirect register: @r4"); }
893 warn("Illegal indirect register: @r5"); }
896 warn("Illegal indirect register: @r6"); }
899 warn("Illegal indirect register: @r7"); }
905 if( !isbit8($1.val.v) )
906 warn("Expression greater than 8-bits");
915 if( !isbit16($1.val.v) )
916 warn("Expression greater than 16-bits");
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");
931 set_ov($$.mode, ($1.val.v&0x0700)>>3 );
933 set_b1($$.mode,$1.val.v&0x00ff);
940 if( !isbit16($1.val.v) )
941 warn("Address greater than 16-bits");
946 set_b1($$.mode, ($1.val.v & 0xff00 ) >> 8 );
947 set_b2($$.mode, ($1.val.v & 0x00ff ) );
955 offset = $1.val.v - (lc+2);
956 if( offset>127 || offset<-128 )
957 warn("Relative offset exceeds -128 / +127");
962 set_b1($$.mode,offset);
969 /* ---------------------------------------------------------------------- */
971 void yyerror(const char *s)
973 warn("%s near \"%s\"", s, get_last_token());
977 /* ----------------------------------------------------------------------
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.
984 * Resultant opcode bytes are passed to genbyte().
986 * Returns the nuumber of bytes that the instruction
991 int makeop(struct opcode * op, struct mode *m, int add)
993 register unsigned int newop;
996 if(pass2) genbyte(op->bytes[0+add]);
1001 newop = op->bytes[ get_md(*m)+add ] | get_ov(*m);
1003 if( get_sz(*m) > 0 ) genbyte( get_b1(*m) );
1004 if( get_sz(*m) > 1 ) genbyte( get_b2(*m) );
1006 return( get_sz(*m)+1 );
1010 /* ----------------------------------------------------------------------
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).
1019 #define indx(a) ( (a)/(32) )
1020 #define bit(a) ( 1 << ((a)%(32)) )
1022 #define getloc(a) (regions[indx(a)] & bit(a))
1023 #define setloc(a) (regions[indx(a)] |= bit(a))
1025 static unsigned long regions[ 0x10000/(32) ];
1031 if( pass2 && getloc(lc) )
1032 error("Location counter overlaps");
1033 if( pass2 ) setloc(lc);
1038 error("Location counter has exceeded 16-bits");
1041 void clear_location_counter(void)
1043 memset(regions, 0, sizeof(regions));
1047 /* ----------------------------------------------------------------------
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.
1054 char *padline(char *line)
1056 static char newline[61];
1060 for(p1=line; pos<sizeof(newline)-1 && *p1; p1++ ) {
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;
1068 newline[pos] = '\0';
1073 /* ----------------------------------------------------------------------
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).
1082 void dumplist(char *txt, int show)
1086 fprintf(listing,show?"%04lX: ":" ",lc);
1089 for(i=0; i<bytecount; i++ ) {
1090 fprintf(listing,"%02X ",bytebuf[i]);
1093 fprintf(listing,"\n ");
1097 fprintf(listing," ");
1099 fprintf(listing," %s\n",padline(txt));
1102 /* ----------------------------------------------------------------------
1104 * Place information into the bytebuf[] array, and also
1105 * call emitbyte with the byte.
1111 if( bytecount < sizeof(bytebuf) )
1112 bytebuf[bytecount++] = b;
1116 void genstr(const char *s)
1122 void genword(unsigned long w)
1124 genbyte( (w & 0xff00) >> 8 );
1125 genbyte( (w & 0x00ff) );