2 /* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
4 * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2.
8 * Paul's XA51 Assembler is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Foobar; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 /* Author contact: paul@pjrc.com */
20 /* parser for the 51-XA assembler, Paul Stoffregen, July 1997 */
30 int arith_opcode, short_opcode, num_op, opcode0, opcode1;
31 int shift_imm_opcode, shift_reg_opcode, rotate_opcode;
32 int stack_addr_opcode, stack_reg_opcode, branch_opcode;
33 int rlist_reg_bank, rlist_bitmask, rlist_size;
34 int db_count, dw_count, i;
35 char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
36 char expr_var[2][MAX_SYMBOL]={{'\0'},{'\0'}};
38 extern char lex_sym_name[];
41 extern void yyrestart(FILE *new_file);
42 extern char * disasm(int byte, int memory_location);
46 void RELOC_FF(unsigned pc, unsigned short offset, short rl) {
48 if ((sym=findSymbol(yytext))) {
50 sprintf (rel_line[rl], "R %d REL_FF 0x%04x %s", offset, pc,
56 void RELOC_FFFF(unsigned pc, unsigned short offset, short rl) {
58 if ((sym=findSymbol(yytext))) {
60 sprintf (rel_line[rl], "R %d REL_FFFF 0x%04x %s", offset, pc,
66 void RELOC_ABS_0F(unsigned short offset, int expr) {
68 if ((sym=findSymbol(expr_var[expr]))) {
70 sprintf (rel_line[expr], "R %d ABS_0F %s", offset, sym->name);
75 void RELOC_ABS_FF(unsigned short offset, int expr) {
77 if ((sym=findSymbol(expr_var[expr]))) {
79 sprintf (rel_line[expr], "R %d ABS_FF %s", offset, sym->name);
84 void RELOC_ABS_03FF(unsigned short offset, int expr) {
87 if ((sym=findSymbol(expr_var[expr]))) {
89 sprintf (rel_line[expr], "R %d ABS_03FF %s", offset, sym->name);
95 void RELOC_ABS_07ff(unsigned short offset, int expr) {
98 if ((sym=findSymbol(expr_var[expr]))) {
100 sprintf (rel_line[expr], "R %d ABS_07ff %s", offset, sym->name);
106 void RELOC_ABS_F0FF(unsigned short offset, int expr) {
109 if ((sym=findSymbol(expr_var[expr]))) {
110 if (sym->mode=='X') {
111 sprintf (rel_line[expr], "R %d ABS_F0FF %s", offset, sym->name);
117 void RELOC_ABS_FFFF(unsigned short offset, int expr) {
120 if ((sym=findSymbol(expr_var[expr]))) {
121 if (sym->mode=='X') {
123 sprintf (rel_line[expr], "R %d ABS_FFFF %s", offset, sym->name);
125 sprintf (rel_line[expr], "R 0 0 00 %02x 02 %02x %02x", current_area,
126 (sym->lk_index>>8)&0xff, sym->lk_index&&0xff);
133 void RELOC_ABS_0F00FF(unsigned short offset, int expr) {
136 if ((sym=findSymbol(expr_var[expr]))) {
137 if (sym->mode=='X') {
138 sprintf (rel_line[expr], "R %d ABS_0F00FF %s", offset, sym->name);
146 %token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
147 %token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
148 %token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
149 %token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
150 %token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
151 %token SETB SEXT SUB SUBB TRAP XCH XOR
152 %token REG DPTR PC A C USP
153 %token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
154 %token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
156 %token AREA AREA_NAME AREA_DESC DS
170 line: linesymbol ':' linenosym {
172 build_sym_list(symbol_name);
173 if (current_area == AREA_BSEG) {
174 mk_bit(symbol_name, current_area);
177 if (p1 || p2) assign_value(symbol_name, MEM_POS, 'R');
184 linenosym: directive EOL {
193 if (p3) out(NULL, 0);
196 | error EOL /* try to recover from any parse error */
199 directive: '.' ORG expr {
207 | '.' EQU symbol ',' expr {
208 if (p1) build_sym_list(symbol_name);
209 if (p1 || p2) assign_value(symbol_name, $5, '?');
212 | normal_or_bit_symbol '=' expr {
213 if (p1) build_sym_list(symbol_name);
214 if (p1 || p2) assign_value(symbol_name, $3, '?');
217 if (p1) build_sym_list(symbol_name);
218 if (p1 || p2) assign_value(symbol_name, $3, 'A');
219 if (p1 || p2) mk_sfr(symbol_name);
222 | '.' BITDEF bitsymbol ',' bit {
224 build_sym_list(symbol_name);
225 mk_bit(symbol_name, 0);
227 if (p1 || p2) assign_value(symbol_name, $5, '?');
230 | bitsymbol BITDEF bit {
232 build_sym_list(symbol_name);
233 mk_bit(symbol_name, 0);
235 if (p1 || p2) assign_value(symbol_name, $3, '?');
238 | bitsymbol BITDEF expr {
240 build_sym_list(symbol_name);
241 mk_bit(symbol_name, 0);
243 if (p1 || p2) assign_value(symbol_name, $3, 'A');
246 | '.' REGDEF regsymbol ',' REG {
248 build_sym_list(symbol_name);
251 if (p1 || p2) assign_value(symbol_name, $5, '?');
254 | regsymbol REGDEF REG {
256 build_sym_list(symbol_name);
259 if (p1 || p2) assign_value(symbol_name, $3, '?');
263 | '.' db_directive bytes {
266 | '.' dw_directive words {
269 | '.' AREA AREA_NAME AREA_DESC {
270 if ($3 < 0 || $3 > NUM_AREAS) {
271 error("Illegal Area Directive");
273 symbol_name[0] = '\0';
278 /* ignore module definition */
282 /* ignore global symbol declaration */
286 /* ignore bit symbol declaration */
290 /* todo: if CSEG, emit some filler bytes */
294 db_directive: DB {db_count = 0;}
297 linesymbol: normal_or_bit_symbol {
298 strcpy(symbol_name, lex_sym_name);
299 if (!strchr(lex_sym_name, ':')) {
300 /* non-local label, remember base name */
301 strcpy(base_symbol_name, lex_sym_name);
303 if (is_target(symbol_name)) pad_with_nop();
306 normal_or_bit_symbol: WORD {$$ = $1;}
310 | bytes ',' byte_element
313 op[db_count] = $1 & 255;
314 if (++db_count >= MAX_DB) {
315 error("too many bytes, use two DB");
320 for(i=1; i < strlen(yytext)-1; i++) {
321 op[db_count++] = yytext[i];
322 if (db_count >= MAX_DB) {
323 error("too many bytes, use two DB");
329 dw_directive: DW {dw_count = 0;}
331 words: words ',' word_element
335 op[dw_count] = $1 & 255;
336 op[dw_count+1] = ($1 >> 8) & 255;
338 if (dw_count >= MAX_DB) {
339 error("too many bytes, use two DW");
347 strcpy(symbol_name, lex_sym_name);
350 bitsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
351 | BIT { strcpy(symbol_name, lex_sym_name); }
354 regsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
355 | REG { strcpy(symbol_name, lex_sym_name); }
358 if ($3 < 0 || $3 > 7) {
359 /* only 8 bits in a byte */
360 error("Only eight bits in a byte");
362 $$ = 100000; /* should really check $1 is valid */
363 if ($1 >= 0x20 && $1 <= 0x3F) {
366 if ($1 >= 0x400 && $1 <= 0x43F) {
367 $$ = ($1 - 0x400) * 8 + $3 + 0x200;
372 if (find_size_reg($1) == SIZE8) {
373 if ($3 < 0 || $3 > 7)
374 error("byte reg has only 8 bits");
375 $$ = reg($1) * 8 + $3;
377 if (find_size_reg($1) == SIZE16) {
378 if ($3 < 0 || $3 > 15)
379 error("word reg has only 16 bits");
380 $$ = reg($1) * 16 + $3;
387 if (p1) build_target_list(lex_sym_name);
390 if ($1 & 1) error("Jump target must be aligned");
395 expr: value {$$ = $1;}
396 | expr '+' expr {$$ = $1 + $3;}
397 | expr '-' expr {$$ = $1 - $3;}
398 | expr '*' expr {$$ = $1 * $3;}
399 | expr '/' expr {$$ = $1 / $3;}
400 | expr '&' expr {$$ = $1 & $3;}
401 | expr '|' expr {$$ = $1 | $3;}
402 | expr '^' expr {$$ = $1 ^ $3;}
403 | expr RSHIFT expr {$$ = $1 >> $3;}
404 | expr LSHIFT expr {$$ = $1 << $3;}
405 | '-' expr %prec UNARY {$$ = $2 * -1;}
406 | '+' expr %prec UNARY {$$ = $2;}
407 | '(' expr ')' {$$ = $2;}
408 | LOW expr %prec UNARY {$$ = $2 & 255;}
409 | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
412 value: NUMBER {$$ = $1;}
416 if (expr_var[0][0]=='\0') {
417 strcpy(expr_var[0], yytext);
419 strcpy(expr_var[1], yytext);
425 rlist_bitmask = 1<<(reg($1) % 8);
426 rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
427 rlist_size = find_size_reg($1);
430 rlist_bitmask |= 1<<(reg($1) % 8);
431 if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
432 error("register list may not mix 0-7/8-15 regs");
433 if (rlist_size != find_size_reg($1))
434 error("register list may not mix 8/16 bit registers");
443 arith_inst REG ',' REG {
445 size = find_size2(inst_size, $2, $4);
446 op[0] = arith_opcode * 16 + size * 8 + 1;
447 op[1] = reg($2) * 16 + reg($4);
449 | arith_inst REG ',' '[' REG ']' {
451 size = find_size1(inst_size, $2);
452 op[0] = arith_opcode * 16 + size * 8 + 2;
453 op[1] = reg($2) * 16 + reg_indirect($5);
455 | arith_inst '[' REG ']' ',' REG {
457 size = find_size1(inst_size, $6);
458 op[0] = arith_opcode * 16 + size * 8 + 2;
459 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
461 | arith_inst REG ',' '[' REG '+' expr ']' {
462 size = find_size1(inst_size, $2);
463 if ($7 >= -128 && $7 <= 127) {
465 op[0] = arith_opcode * 16 + size * 8 + 4;
466 op[1] = reg($2) * 16 + reg_indirect($5);
467 op[2] = ($7 >= 0) ? $7 : 256 + $7;
471 op[0] = arith_opcode * 16 + size * 8 + 5;
472 op[1] = reg($2) * 16 + reg_indirect($5);
473 op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
474 op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
478 | arith_inst '[' REG '+' expr ']' ',' REG {
479 size = find_size1(inst_size, $8);
480 if ($5 >= -128 && $5 <= 127) {
482 op[0] = arith_opcode * 16 + size * 8 + 4;
483 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
484 op[2] = ($5 >= 0) ? $5 : 256 + $5;
488 op[0] = arith_opcode * 16 + size * 8 + 5;
489 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
490 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
491 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
495 | arith_inst REG ',' '[' REG '+' ']' {
497 size = find_size1(inst_size, $2);
498 op[0] = arith_opcode * 16 + size * 8 + 3;
499 op[1] = reg($2) * 16 + reg_indirect($5);
501 | arith_inst '[' REG '+' ']' ',' REG {
503 size = find_size1(inst_size, $7);
504 op[0] = arith_opcode * 16 + size * 8 + 3;
505 op[1] = reg($7) * 16 + 8 + reg_indirect($3);
507 | arith_inst WORD ',' REG {
509 size = find_size1(inst_size, $4);
510 op[0] = arith_opcode * 16 + size * 8 + 6;
511 op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
512 op[2] = lsb(direct_addr($2));
513 RELOC_ABS_07ff(1, 0);
515 | arith_inst REG ',' WORD {
517 size = find_size1(inst_size, $2);
518 op[0] = arith_opcode * 16 + size * 8 + 6;
519 op[1] = reg($2) * 16 + msb(direct_addr($4));
520 op[2] = lsb(direct_addr($4));
521 RELOC_ABS_07ff(1, 0);
523 | arith_inst REG ',' '#' expr {
524 size = find_size1(inst_size, $2);
528 op[1] = reg($2) * 16 + arith_opcode;
529 op[2] = imm_data8($5);
534 op[1] = reg($2) * 16 + arith_opcode;
535 op[2] = msb(imm_data16($5));
536 op[3] = lsb(imm_data16($5));
537 RELOC_ABS_FFFF (2, 0);
540 | arith_inst '[' REG ']' ',' '#' expr {
541 size = find_size0(inst_size);
545 op[1] = reg_indirect($3) * 16 + arith_opcode;
546 op[2] = imm_data8($7);
551 op[1] = reg_indirect($3) * 16 + arith_opcode;
552 op[2] = msb(imm_data16($7));
553 op[3] = lsb(imm_data16($7));
554 RELOC_ABS_FFFF (2, 0);
557 | arith_inst '[' REG '+' ']' ',' '#' expr {
558 size = find_size0(inst_size);
562 op[1] = reg_indirect($3) * 16 + arith_opcode;
563 op[2] = imm_data8($8);
568 op[1] = reg_indirect($3) * 16 + arith_opcode;
569 op[2] = msb(imm_data16($8));
570 op[3] = lsb(imm_data16($8));
571 RELOC_ABS_FFFF (2, 0);
574 | arith_inst '[' REG '+' expr ']' ',' '#' expr {
575 size = find_size0(inst_size);
576 if ($5 >= -128 && $5 <= 127) {
580 op[1] = reg_indirect($3) * 16 + arith_opcode;
581 op[2] = ($5 >= 0) ? $5 : 256 + $5;
582 op[3] = imm_data8($9);
588 op[1] = reg_indirect($3) * 16 + arith_opcode;
589 op[2] = ($5 >= 0) ? $5 : 256 + $5;
590 op[3] = msb(imm_data16($9));
591 op[4] = lsb(imm_data16($9));
593 RELOC_ABS_FFFF(3, 1);
599 op[1] = reg_indirect($3) * 16 + arith_opcode;
600 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
601 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
602 op[4] = imm_data8($9);
608 op[1] = reg_indirect($3) * 16 + arith_opcode;
609 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
610 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
611 op[4] = msb(imm_data16($9));
612 op[5] = lsb(imm_data16($9));
613 RELOC_ABS_FFFF(2, 0);
614 RELOC_ABS_FFFF(4, 1);
618 | arith_inst WORD ',' '#' expr {
619 size = find_size0(inst_size);
623 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
624 op[2] = lsb(direct_addr($2));
625 op[3] = imm_data8($5);
631 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
632 op[2] = lsb(direct_addr($2));
633 op[3] = msb(imm_data16($5));
634 op[4] = lsb(imm_data16($5));
636 RELOC_ABS_FFFF (3,1);
640 /* the next 8 instructions are MOV, but because MOV was used in the */
641 /* arith_inst group, it will cause a shift/reduce conflict if used */
642 /* directly below... so we're forced to use arith_inst and then */
643 /* add a bit of code to make sure it was MOV and not the other ones */
645 | arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
646 /* this addr mode is only valid for MOV */
647 if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
648 size = find_size0(inst_size);
650 op[0] = 0x90 + size * 8;
651 op[1] = reg_indirect($3) * 16 + reg_indirect($8);
653 | arith_inst WORD ',' '[' REG ']' {
654 /* this addr mode is only valid for MOV */
655 if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
656 size = find_size0(inst_size);
658 op[0] = 0xA0 + size * 8;
659 op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
660 op[2] = lsb(direct_addr($2));
661 RELOC_ABS_07ff(1, 0);
663 | arith_inst '[' REG ']' ',' WORD {
664 /* this addr mode is only valid for MOV */
665 if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
666 size = find_size0(inst_size);
668 op[0] = 0xA0 + size * 8;
669 op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
670 op[2] = lsb(direct_addr($6));
671 RELOC_ABS_07ff(1, 0);
673 | arith_inst WORD ',' WORD {
674 /* this addr mode is only valid for MOV */
675 if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
676 size = find_size0(inst_size);
678 op[0] = 0x97 + size * 8;
679 op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
680 op[2] = lsb(direct_addr($2));
681 op[3] = lsb(direct_addr($4));
682 RELOC_ABS_F0FF(1, 0);
683 RELOC_ABS_0F00FF(1, 1);
685 | arith_inst REG ',' USP {
686 /* this addr mode is only valid for MOV */
687 if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
690 op[1] = reg($2) * 16 + 15;
692 | arith_inst USP ',' REG {
693 /* this addr mode is only valid for MOV */
694 if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
697 op[1] = reg($4) * 16 + 15;
699 | arith_inst C ',' bit {
700 /* this addr mode is only valid for MOV */
701 if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
704 op[1] = 0x20 + msb(bit_addr($4));
705 op[2] = lsb(bit_addr($4));
706 RELOC_ABS_03FF(1, 0);
708 | arith_inst bit ',' C {
709 /* this addr mode is only valid for MOV */
710 if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
713 op[1] = 0x30 + msb(bit_addr($2));
714 op[2] = lsb(bit_addr($2));
715 RELOC_ABS_03FF(1, 0);
718 | MOVC REG ',' '[' REG '+' ']' {
719 size = find_size1(inst_size, $2);
721 op[0] = 0x80 + size * 8;
722 op[1] = reg($2) * 16 + reg_indirect($5);
724 | MOVC A ',' '[' A '+' DPTR ']' {
729 | MOVC A ',' '[' A '+' PC ']' {
734 | MOVX REG ',' '[' REG ']' {
736 size = find_size1(inst_size, $2);
737 op[0] = 0xA7 + size * 8;
738 op[1] = reg($2) * 16 + reg_indirect($5);
740 | MOVX '[' REG ']' ',' REG {
742 size = find_size1(inst_size, $6);
743 op[0] = 0xA7 + size * 8;
744 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
748 size = find_size2(inst_size, $2, $4);
749 op[0] = 0x60 + size * 8;
750 op[1] = reg($2) * 16 + reg($4);
752 | XCH REG ',' '[' REG ']' {
754 size = find_size1(inst_size, $2);
755 op[0] = 0x50 + size * 8;
756 op[1] = reg($2) * 16 + reg_indirect($5);
760 size = find_size1(inst_size, $2);
761 op[0] = 0xA0 + size * 8;
762 op[1] = reg($2) * 16 + msb(direct_addr($4));
763 op[2] = lsb(direct_addr($4));
764 RELOC_ABS_07ff(1, 0);
766 | short_data_inst REG ',' '#' expr {
768 size = find_size1(inst_size, $2);
769 op[0] = short_opcode + size * 8 + 1;
770 op[1] = reg($2) * 16 + imm_data4_signed($5);
773 | short_data_inst '[' REG ']' ',' '#' expr {
775 size = find_size0(inst_size);
776 op[0] = short_opcode + size * 8 + 2;
777 op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
780 | short_data_inst '[' REG '+' ']' ',' '#' expr {
782 size = find_size0(inst_size);
783 op[0] = short_opcode + size * 8 + 3;
784 op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
787 | short_data_inst '[' REG '+' expr ']' ',' '#' expr {
788 size = find_size0(inst_size);
789 if ($5 >= -128 && $5 <= 127) {
791 op[0] = short_opcode + size * 8 + 4;
792 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
793 op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
798 op[0] = short_opcode + size * 8 + 5;
799 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
800 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
801 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
803 RELOC_ABS_FFFF(2, 0);
806 | short_data_inst expr ',' '#' expr {
808 size = find_size0(inst_size);
809 op[0] = short_opcode + size * 8 + 6;
810 op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
811 op[2] = lsb(direct_addr($2));
817 op[1] = 0x40 + msb(bit_addr($4));
818 op[2] = lsb(bit_addr($4));
819 RELOC_ABS_03FF(1, 0);
821 | ANL C ',' '/' bit {
824 op[1] = 0x50 + msb(bit_addr($5));
825 op[2] = lsb(bit_addr($5));
826 RELOC_ABS_03FF(1, 0);
832 op[1] = 0x60 + msb(bit_addr($4));
833 op[2] = lsb(bit_addr($4));
834 RELOC_ABS_03FF(1, 0);
836 | ORL C ',' '/' bit {
839 op[1] = 0x70 + msb(bit_addr($5));
840 op[2] = lsb(bit_addr($5));
841 RELOC_ABS_03FF(1, 0);
846 op[1] = msb(bit_addr($2));
847 op[2] = lsb(bit_addr($2));
848 RELOC_ABS_03FF(1, 0);
853 op[1] = 0x10 + msb(bit_addr($2));
854 op[2] = lsb(bit_addr($2));
855 RELOC_ABS_03FF(1, 0);
857 | logical_shift_inst REG ',' REG {
858 size = find_size1(inst_size, $2);
859 if (find_size_reg($4) != SIZE8)
860 error("Second register in logical shift must be byte size");
862 op[0] = shift_reg_opcode;
864 case SIZE8: op[0] += 0; break;
865 case SIZE16: op[0] += 8; break;
866 case SIZE32: op[0] += 12; break;
868 op[1] = reg($2) * 16 + reg($4);
870 | logical_shift_inst REG ',' '#' NUMBER {
871 size = find_size1(inst_size, $2);
873 if (shift_imm_opcode == -1)
874 error("NORM may not use a constant");
875 op[0] = shift_imm_opcode;
877 case SIZE8: op[0] += 0; break;
878 case SIZE16: op[0] += 8; break;
879 case SIZE32: op[0] += 12; break;
884 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
887 op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
900 op[1] = 0x30 + imm_data4_unsigned($3);
904 size = find_size1(inst_size, $2);
905 op[0] = 0x90 + size * 8;
906 op[1] = reg($2) * 16 + 10;
911 op[1] = reg($2) * 16 + 8;
915 size = find_size1(inst_size, $2);
916 op[0] = 0x90 + size * 8;
917 op[1] = reg($2) * 16 + 11;
921 size = find_size1(inst_size, $2);
922 op[0] = 0x90 + size * 8;
923 op[1] = reg($2) * 16 + 9;
926 | rotate_inst REG ',' '#' NUMBER {
928 size = find_size1(inst_size, $2);
929 op[0] = rotate_opcode + size * 8;
930 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
934 | LEA REG ',' REG '+' expr {
935 if ($6 >= -128 && $6 <= 127) {
938 op[1] = reg($2) * 16 + reg_indirect($4);
939 op[2] = ($6 >= 0) ? $6 : 256 + $6;
943 op[1] = reg($2) * 16 + reg_indirect($4);
944 op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
945 op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
946 RELOC_ABS_FFFF(2, 0);
951 size = find_size0(inst_size);
952 op[0] = msb(stack_addr_opcode) + size * 8;
953 op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
954 op[2] = lsb(direct_addr($2));
955 RELOC_ABS_07ff(1, 0);
959 if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
960 error("inst specifies different size than registers used");
961 op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
962 op[1] = rlist_bitmask;
968 size = find_size2(inst_size, $2, $4);
970 op[1] = reg($2) * 16 + reg($4);
974 size = find_size2(inst_size, $2, $4);
977 op[1] = reg($2) * 16 + reg($4);
980 op[1] = reg($2) * 16 + reg($4);
983 | MUL REG ',' '#' expr {
985 size = find_size1(inst_size, $2);
988 op[2] = msb(imm_data16($5));
989 op[3] = lsb(imm_data16($5));
990 RELOC_ABS_FFFF(2, 0);
992 | MULU REG ',' '#' expr {
993 size = find_size2(inst_size, $2, $4);
997 op[1] = reg($2) * 16;
998 op[2] = imm_data8($5);
1003 op[1] = reg($2) * 16;
1004 op[2] = msb(imm_data16($5));
1005 op[3] = lsb(imm_data16($5));
1006 RELOC_ABS_FFFF(2, 0);
1011 size = find_size2(inst_size, $2, $4);
1014 error("Singed DIV can't be 8 bit size"); break;
1017 op[1] = reg($2) * 16 + reg($4);
1021 op[1] = (reg($2) / 2) * 32 + reg($4);
1025 | DIVU REG ',' REG {
1027 size = find_size2(inst_size, $2, $4);
1031 op[1] = reg($2) * 16 + reg($4);
1035 op[1] = reg($2) * 16 + reg($4);
1039 op[1] = (reg($2) / 2) * 32 + reg($4);
1043 | DIV REG ',' '#' expr {
1044 size = find_size1(inst_size, $2);
1047 error("Singed DIV can't be 8 bit size"); break;
1051 op[1] = reg($2) * 16 + 11;
1052 op[2] = imm_data8($5);
1058 op[1] = (reg($2) / 2) * 32 + 9;
1059 op[2] = msb(imm_data16($5));
1060 op[3] = lsb(imm_data16($5));
1061 RELOC_ABS_FFFF(2, 0);
1065 | DIVU REG ',' '#' expr {
1066 size = find_size1(inst_size, $2);
1071 op[1] = reg($2) * 16 + 1;
1072 op[2] = imm_data8($5);
1078 op[1] = reg($2) * 16 + 3;
1079 op[2] = imm_data8($5);
1085 op[1] = (reg($2) / 2) * 32 + 1;
1086 op[2] = msb(imm_data16($5));
1087 op[3] = lsb(imm_data16($5));
1088 RELOC_ABS_FFFF(2, 0);
1092 | CALL '[' REG ']' {
1100 op[1] = ($2 >> 8) & 255;
1102 op[3] = ($2 >> 16) & 255;
1107 op[1] = ($2 >> 8) & 255;
1109 op[3] = ($2 >> 16) & 255;
1114 op[1] = 0x70 + reg_indirect($3);
1116 | JMP '[' A '+' DPTR ']' {
1121 | JMP '[' '[' REG '+' ']' ']' {
1124 op[1] = 0x60 + reg_indirect($4);
1130 op[1] = msb(rel16(MEM_POS + $$, $2));
1131 op[2] = lsb(rel16(MEM_POS + $$, $2));
1132 RELOC_FFFF(MEM_POS+$$,1,0);
1138 op[1] = msb(rel16(MEM_POS + $$, $2));
1139 op[2] = lsb(rel16(MEM_POS + $$, $2));
1140 RELOC_FFFF(MEM_POS+$$,1,0);
1142 | branch_inst jmpaddr {
1144 op[0] = branch_opcode;
1145 op[1] = rel8(MEM_POS + $$, $2);
1146 RELOC_FF(MEM_POS + $$, 1,0);
1148 | CJNE REG ',' expr ',' jmpaddr {
1150 size = find_size1(inst_size, $2);
1151 op[0] = 0xE2 + size * 8;
1152 op[1] = reg($2) * 16 + msb(direct_addr($4));
1153 op[2] = lsb(direct_addr($4));
1154 op[3] = rel8(MEM_POS + $$, $6);
1155 RELOC_ABS_07ff(1, 0);
1156 RELOC_FF(MEM_POS + $$, 3,1);
1158 | CJNE REG ',' '#' expr ',' jmpaddr {
1159 size = find_size1(inst_size, $2);
1160 if (size == SIZE8) {
1163 op[1] = reg($2) * 16;
1164 op[2] = rel8(MEM_POS + $$, $7);
1165 op[3] = imm_data8($5);
1170 op[1] = reg($2) * 16;
1171 op[2] = rel8(MEM_POS + $$, $7);
1172 op[3] = msb(imm_data16($5));
1173 op[4] = lsb(imm_data16($5));
1174 RELOC_ABS_FFFF(3, 0);
1177 | CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
1178 size = find_size0(inst_size);
1179 if (size == SIZE8) {
1182 op[1] = reg_indirect($3) * 16 + 8;
1183 op[2] = rel8(MEM_POS + $$, $9);
1184 op[3] = imm_data8($7);
1189 op[1] = reg_indirect($3) * 16 + 8;
1190 op[2] = rel8(MEM_POS + $$, $9);
1191 op[3] = msb(imm_data16($7));
1192 op[4] = lsb(imm_data16($7));
1193 RELOC_ABS_FFFF(3, 0);
1196 | DJNZ REG ',' jmpaddr {
1198 size = find_size1(inst_size, $2);
1199 op[0] = 0x87 + size * 8;
1200 op[1] = reg($2) * 16 + 8;
1201 op[2] = rel8(MEM_POS + $$, $4);
1202 RELOC_FF(MEM_POS+$$, 2, 0);
1206 | DJNZ WORD ',' jmpaddr {
1208 size = find_size0(inst_size);
1209 op[0] = 0xE2 + size * 8;
1210 op[1] = msb(direct_addr($2)) + 8;
1211 op[2] = lsb(direct_addr($2));
1212 op[3] = rel8(MEM_POS + $$, $4);
1213 RELOC_ABS_07ff(1, 0);
1214 RELOC_FF(MEM_POS + $$, 3, 1)
1217 | JB bit ',' jmpaddr {
1220 op[1] = 0x80 + msb(bit_addr($2));
1221 op[2] = lsb(bit_addr($2));
1222 op[3] = rel8(MEM_POS + $$, $4);
1223 RELOC_ABS_03FF(1, 0);
1224 RELOC_FF(MEM_POS + $$, 3, 1);
1227 | JBC bit ',' jmpaddr {
1230 op[1] = 0xC0 + msb(bit_addr($2));
1231 op[2] = lsb(bit_addr($2));
1232 op[3] = rel8(MEM_POS + $$, $4);
1233 RELOC_ABS_03FF(1, 0);
1234 RELOC_FF(MEM_POS + $$, 3, 1);
1237 | JNB bit ',' jmpaddr {
1240 op[1] = 0xA0 + msb(bit_addr($2));
1241 op[2] = lsb(bit_addr($2));
1242 op[3] = rel8(MEM_POS + $$, $4);
1243 RELOC_ABS_03FF(1, 0);
1244 RELOC_FF(MEM_POS + $$, 3, 1);
1249 ADD {arith_opcode = 0;}
1250 | ADDC {arith_opcode = 1;}
1251 | AND {arith_opcode = 5;}
1252 | CMP {arith_opcode = 4;}
1253 | MOV {arith_opcode = 8;}
1254 | OR {arith_opcode = 6;}
1255 | SUB {arith_opcode = 2;}
1256 | SUBB {arith_opcode = 3;}
1257 | XOR {arith_opcode = 7;}
1260 ADDS {short_opcode = 0xA0;}
1261 | MOVS {short_opcode = 0xB0;}
1264 ASL {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
1265 | ASR {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
1266 | LSR {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
1267 | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
1270 RL {rotate_opcode = 0xD3;}
1271 | RLC {rotate_opcode = 0xD7;}
1272 | RR {rotate_opcode = 0xD0;}
1273 | RRC {rotate_opcode = 0xD7;}
1276 POP {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
1277 | POPU {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
1278 | PUSH {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
1279 | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
1282 BKPT {num_op = 1; opcode0 = 255; opcode1 = 0;}
1283 | NOP {num_op = 1; opcode0 = 0; opcode1 = 0;}
1284 | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
1285 | RET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
1286 | RETI {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
1289 BCC {branch_opcode = 0xF0;}
1290 | BCS {branch_opcode = 0xF1;}
1291 | BEQ {branch_opcode = 0xF3;}
1292 | BG {branch_opcode = 0xF8;}
1293 | BGE {branch_opcode = 0xFA;}
1294 | BGT {branch_opcode = 0xFC;}
1295 | BL {branch_opcode = 0xF9;}
1296 | BLE {branch_opcode = 0xFD;}
1297 | BLT {branch_opcode = 0xFB;}
1298 | BMI {branch_opcode = 0xF7;}
1299 | BNE {branch_opcode = 0xF2;}
1300 | BNV {branch_opcode = 0xF4;}
1301 | BOV {branch_opcode = 0xF5;}
1302 | BPL {branch_opcode = 0xF6;}
1303 | BR {branch_opcode = 0xFE;}
1304 | JZ {branch_opcode = 0xEC;}
1305 | JNZ {branch_opcode = 0xEE;}
1312 int reg(int reg_spec)
1314 return reg_spec & 15;
1317 int reg_indirect(int reg_spec)
1319 if (reg_spec & BYTE_REG)
1320 error("Indirect addressing may not use byte registers");
1321 if ((reg_spec & 15) > 7)
1322 error("Only R0 through R7 may be used for indirect addr");
1323 return reg_spec & 7;
1326 int rel16(int pos, int dest)
1330 if (!p3) return 0; /* don't bother unless writing code */
1331 if (dest & (BRANCH_SPACING - 1))
1332 error("Attempt to jump to unaligned location");
1333 pos &= ~(BRANCH_SPACING - 1);
1334 rel = (dest - pos) / BRANCH_SPACING;
1335 if (rel < -32768 || rel > 32767)
1336 error("Attempt to jump out of 16 bit relative range");
1337 if (rel < 0) rel += 65536;
1341 int rel8(int pos, int dest)
1345 if (!p3) return 0; /* don't bother unless writing code */
1346 if (dest & (BRANCH_SPACING - 1))
1347 error("Attempt to jump to unaligned location");
1348 pos &= ~(BRANCH_SPACING - 1);
1349 rel = (dest - pos) / BRANCH_SPACING;
1350 if (rel < -128 || rel > 127)
1351 error("Attempt to jump out of 16 bit relative range");
1352 if (rel < 0) rel += 256;
1358 return (value >> 8) & 255;
1366 int direct_addr(int value)
1370 if (value < 0 || value > 2047) {
1371 sprintf(buf, "illegal value (%d) for direct address", value);
1377 int imm_data4_signed(int value)
1379 if (value < -8 || value > 7)
1380 error("illegal 4 bit (signed) value");
1381 if (value >= 0) return value;
1382 else return (16 + value);
1385 int imm_data4_unsigned(int value)
1387 if (value < 0 || value > 15)
1388 error("illegal 4 bit (unsigned) value");
1392 int imm_data5_unsigned(int value)
1394 if (value < 0 || value > 31)
1395 error("illegal 5 bit (unsigned) value");
1399 int imm_data8(int value)
1401 if (value < -128 || value > 255)
1402 error("illegal 8 bit value");
1403 if (value >= 0) return value;
1404 else return (256 + value);
1407 int imm_data16(int value)
1409 if (value < -32728 || value > 65535)
1410 error("illegal 16 bit value");
1411 if (value >= 0) return value;
1412 else return (65536 + value);
1415 int bit_addr(int value)
1417 if (value < 0 || value > 1023) {
1418 fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
1420 error("illegal bit address");
1426 int find_size_reg(int op1spec)
1428 int op1size=UNKNOWN;
1430 if (op1spec & BYTE_REG) op1size = SIZE8;
1431 if (op1spec & WORD_REG) op1size = SIZE16;
1432 if (op1size == UNKNOWN)
1433 error("Register without implied size");
1437 int find_size0(int isize)
1439 if (isize == UNKNOWN)
1440 error("Can't determine data size from instruction");
1444 int find_size1(int isize, int op1spec)
1446 int op1size=UNKNOWN;
1448 if (op1spec & BYTE_REG) op1size = SIZE8;
1449 if (op1spec & WORD_REG) op1size = SIZE16;
1450 if (op1size == UNKNOWN)
1451 error("Register without implied size");
1453 if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
1454 if (isize == UNKNOWN) return op1size;
1456 if (isize != op1size)
1457 error("data size of register and inst don't agree");
1462 int find_size2(int isize, int op1spec, int op2spec)
1464 int op1size=UNKNOWN, op2size=UNKNOWN;
1466 if (op1spec & BYTE_REG) op1size = SIZE8;
1467 if (op1spec & WORD_REG) op1size = SIZE16;
1468 if (op1size == UNKNOWN)
1469 error("Register without implied size");
1470 if (op2spec & BYTE_REG) op2size = SIZE8;
1471 if (op2spec & WORD_REG) op2size = SIZE16;
1472 if (op1size == UNKNOWN)
1473 error("Register without implied size");
1475 if (op1size != op2size)
1476 error("data sizes of two registers don't agree");
1477 if (isize == UNKNOWN) return op1size;
1479 if (isize != op1size)
1480 error("data size of registers and inst don't agree");
1485 int yyerror(char *s)
1487 if (yytext[0] >= 32) {
1488 fprintf(stderr, "%s near '%s', line %d\n",
1491 fprintf(stderr, "%s, line %d\n", s, lineno - 1);