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 operand[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 where, unsigned pc, short rl) {
47 // pc = PC of the next instruction
49 if ((sym=findSymbol(operand[0]))) {
50 if (sym->mode=='X' || sym->area!=current_area) {
51 sprintf (rel_line[rl], "R %04x REL_FF %s %04x",
52 where, sym->name, pc);
57 void RELOC_FFFF(unsigned where, unsigned pc, short rl) {
59 if ((sym=findSymbol(operand[0]))) {
60 if (sym->mode=='X' || sym->area!=current_area) {
61 sprintf (rel_line[rl], "R %04x REL_FFFF %s %04x",
62 where, sym->name, pc);
67 void RELOC_ABS_0F(unsigned where, int seq) {
69 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
70 sprintf (rel_line[seq], "R %04x ABS_0F %s 0", where, sym->name);
74 void RELOC_BIT_03FF(unsigned where, int seq) {
76 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
77 sprintf (rel_line[seq], "R %04x BIT_03FF %s 0", where, sym->name);
81 void RELOC_DIR_07FF(unsigned where, int seq) {
83 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
84 sprintf (rel_line[seq], "R %04x DIR_07FF %s 0", where, sym->name);
88 void RELOC_DIR_70FF(unsigned where, int seq) {
90 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
91 sprintf (rel_line[seq], "R %04x DIR_70FF %s 0", where, sym->name);
95 void RELOC_ABS_FF(unsigned where, int seq) {
97 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
98 sprintf (rel_line[seq], "R %04x DIR_FF %s 0", where, sym->name);
102 void RELOC_ABS_FFFF(unsigned where, int seq) {
104 if ((sym=findSymbol(operand[seq]))) {
107 // sfr or sbit, already in instruction
109 // equat, already in instruction
112 // external reference
113 sprintf (rel_line[seq], "R %04x ABS_FFFF %s %04x", where, sym->name,
117 // absolute in current segment
118 sprintf (rel_line[seq], "R %04x ABS_PC PC %04x", where, sym->value);
121 fprintf (stderr, "unknown ABS_FFFF\n");
127 void RELOC_DIR_0700FF(unsigned where, int seq) {
129 if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
130 sprintf (rel_line[seq], "R %04x ABS_0700FF %s 0", where, sym->name);
136 %token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
137 %token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
138 %token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
139 %token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
140 %token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
141 %token SETB SEXT SUB SUBB TRAP XCH XOR
142 %token REG DPTR PC A C USP
143 %token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
144 %token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
146 %token AREA AREA_NAME AREA_DESC DS
159 line: linesymbol ':' linenosym {
161 build_sym_list(symbol_name);
162 if (current_area == AREA_BSEG) {
163 mk_bit(symbol_name, current_area);
166 if (p1 || p2) assign_value(symbol_name, MEM_POS, 'R');
170 if (!is_abs(symbol_name)) {
175 linenosym: directive EOL {
184 if (p3) out(NULL, 0);
187 | error EOL /* try to recover from any parse error */
190 directive: '.' ORG expr {
198 | '.' EQU symbol ',' expr {
199 if (p1) build_sym_list(symbol_name);
200 if (p1 || p2) assign_value(symbol_name, $5, '?');
204 if (p1) build_sym_list(symbol_name);
205 if (p1 || p2) assign_value(symbol_name, $3, '=');
208 if (p1) build_sym_list(symbol_name);
209 if (p1 || p2) assign_value(symbol_name, $3, 'A');
210 if (p1 || p2) mk_sfr(symbol_name);
213 | '.' BITDEF bitsymbol ',' bit {
215 build_sym_list(symbol_name);
216 mk_bit(symbol_name, 0);
218 if (p1 || p2) assign_value(symbol_name, $5, '?');
221 | bitsymbol BITDEF bit {
223 build_sym_list(symbol_name);
224 mk_bit(symbol_name, 0);
226 if (p1 || p2) assign_value(symbol_name, $3, '?');
229 | bitsymbol BITDEF expr {
231 build_sym_list(symbol_name);
232 mk_bit(symbol_name, 0);
234 if (p1 || p2) assign_value(symbol_name, $3, 'A');
237 | '.' REGDEF regsymbol ',' REG {
239 build_sym_list(symbol_name);
242 if (p1 || p2) assign_value(symbol_name, $5, '?');
245 | regsymbol REGDEF REG {
247 build_sym_list(symbol_name);
250 if (p1 || p2) assign_value(symbol_name, $3, '?');
254 | '.' db_directive bytes {
257 | '.' dw_directive words {
260 | '.' AREA AREA_NAME AREA_DESC {
261 if ($3 < 0 || $3 > NUM_AREAS) {
262 error("Illegal Area Directive");
264 symbol_name[0] = '\0';
269 /* ignore module definition */
273 mk_global(lex_sym_name);
274 /* ignore global symbol declaration */
278 /* ignore bit symbol declaration */
282 /* todo: if CSEG, emit some filler bytes */
286 db_directive: DB {db_count = 0;}
289 linesymbol: normal_or_bit_symbol {
290 strcpy(symbol_name, lex_sym_name);
291 if (!strchr(lex_sym_name, ':')) {
292 /* non-local label, remember base name */
293 strcpy(base_symbol_name, lex_sym_name);
295 if (is_target(symbol_name)) pad_with_nop();
298 normal_or_bit_symbol: WORD {$$ = $1;}
302 | bytes ',' byte_element
305 op[db_count] = $1 & 255;
306 if (++db_count >= MAX_DB) {
307 error("too many bytes, use two DB");
312 for(i=1; i < strlen(yytext)-1; i++) {
313 op[db_count++] = yytext[i];
314 if (db_count >= MAX_DB) {
315 error("too many bytes, use two DB");
321 dw_directive: DW {dw_count = 0;}
323 words: words ',' word_element
327 op[dw_count] = $1 & 255;
328 op[dw_count+1] = ($1 >> 8) & 255;
330 if (dw_count >= MAX_DB) {
331 error("too many bytes, use two DW");
339 strcpy(symbol_name, lex_sym_name);
342 bitsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
343 | BIT { strcpy(symbol_name, lex_sym_name); }
346 regsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
347 | REG { strcpy(symbol_name, lex_sym_name); }
350 if ($3 < 0 || $3 > 7) {
351 /* only 8 bits in a byte */
352 error("Only eight bits in a byte");
354 $$ = 100000; /* should really check $1 is valid */
355 if ($1 >= 0x20 && $1 <= 0x3F) {
358 if ($1 >= 0x400 && $1 <= 0x43F) {
359 $$ = ($1 - 0x400) * 8 + $3 + 0x200;
364 if (find_size_reg($1) == SIZE8) {
365 if ($3 < 0 || $3 > 7)
366 error("byte reg has only 8 bits");
367 $$ = reg($1) * 8 + $3;
369 if (find_size_reg($1) == SIZE16) {
370 if ($3 < 0 || $3 > 15)
371 error("word reg has only 16 bits");
372 $$ = reg($1) * 16 + $3;
379 if (p1) build_target_list(lex_sym_name);
382 if ($1 & 1) error("Jump target must be aligned");
387 expr: value {$$ = $1;}
388 | expr '+' expr {$$ = $1 + $3;}
389 | expr '-' expr {$$ = $1 - $3;}
390 | expr '*' expr {$$ = $1 * $3;}
391 | expr '/' expr {$$ = $1 / $3;}
392 | expr '&' expr {$$ = $1 & $3;}
393 | expr '|' expr {$$ = $1 | $3;}
394 | expr '^' expr {$$ = $1 ^ $3;}
395 | expr RSHIFT expr {$$ = $1 >> $3;}
396 | expr LSHIFT expr {$$ = $1 << $3;}
397 | '-' expr %prec UNARY {$$ = $2 * -1;}
398 | '+' expr %prec UNARY {$$ = $2;}
399 | '(' expr ')' {$$ = $2;}
400 | LOW expr %prec UNARY {$$ = $2 & 255;}
401 | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
404 value: NUMBER {$$ = $1;}
409 rlist_bitmask = 1<<(reg($1) % 8);
410 rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
411 rlist_size = find_size_reg($1);
414 rlist_bitmask |= 1<<(reg($1) % 8);
415 if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
416 error("register list may not mix 0-7/8-15 regs");
417 if (rlist_size != find_size_reg($1))
418 error("register list may not mix 8/16 bit registers");
427 arith_inst REG ',' REG {
429 size = find_size2(inst_size, $2, $4);
430 op[0] = arith_opcode * 16 + size * 8 + 1;
431 op[1] = reg($2) * 16 + reg($4);
433 | arith_inst REG ',' '[' REG ']' {
435 size = find_size1(inst_size, $2);
436 op[0] = arith_opcode * 16 + size * 8 + 2;
437 op[1] = reg($2) * 16 + reg_indirect($5);
439 | arith_inst '[' REG ']' ',' REG {
441 size = find_size1(inst_size, $6);
442 op[0] = arith_opcode * 16 + size * 8 + 2;
443 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
445 | arith_inst REG ',' '[' REG '+' expr ']' {
446 size = find_size1(inst_size, $2);
447 if ($7 >= -128 && $7 <= 127) {
449 op[0] = arith_opcode * 16 + size * 8 + 4;
450 op[1] = reg($2) * 16 + reg_indirect($5);
451 op[2] = ($7 >= 0) ? $7 : 256 + $7;
452 RELOC_ABS_FF(MEM_POS+2,0);
455 op[0] = arith_opcode * 16 + size * 8 + 5;
456 op[1] = reg($2) * 16 + reg_indirect($5);
457 op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
458 op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
459 RELOC_ABS_FFFF(MEM_POS+2,0);
462 | arith_inst '[' REG '+' expr ']' ',' REG {
463 size = find_size1(inst_size, $8);
464 if ($5 >= -128 && $5 <= 127) {
466 op[0] = arith_opcode * 16 + size * 8 + 4;
467 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
468 op[2] = ($5 >= 0) ? $5 : 256 + $5;
469 RELOC_ABS_FF(MEM_POS+2,0);
472 op[0] = arith_opcode * 16 + size * 8 + 5;
473 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
474 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
475 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
476 RELOC_ABS_FFFF(MEM_POS+2,0);
479 | arith_inst REG ',' '[' REG '+' ']' {
481 size = find_size1(inst_size, $2);
482 op[0] = arith_opcode * 16 + size * 8 + 3;
483 op[1] = reg($2) * 16 + reg_indirect($5);
485 | arith_inst '[' REG '+' ']' ',' REG {
487 size = find_size1(inst_size, $7);
488 op[0] = arith_opcode * 16 + size * 8 + 3;
489 op[1] = reg($7) * 16 + 8 + reg_indirect($3);
491 | arith_inst WORD ',' REG {
493 size = find_size1(inst_size, $4);
494 op[0] = arith_opcode * 16 + size * 8 + 6;
495 op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
496 op[2] = lsb(direct_addr($2));
497 RELOC_DIR_07FF(MEM_POS+1, 0);
499 | arith_inst REG ',' WORD {
501 size = find_size1(inst_size, $2);
502 op[0] = arith_opcode * 16 + size * 8 + 6;
503 op[1] = reg($2) * 16 + msb(direct_addr($4));
504 op[2] = lsb(direct_addr($4));
505 RELOC_DIR_07FF(MEM_POS+1, 0);
507 | arith_inst REG ',' '#' expr {
508 size = find_size1(inst_size, $2);
512 op[1] = reg($2) * 16 + arith_opcode;
513 op[2] = imm_data8($5);
514 RELOC_ABS_FF(MEM_POS+2, 0);
518 op[1] = reg($2) * 16 + arith_opcode;
519 op[2] = msb(imm_data16($5));
520 op[3] = lsb(imm_data16($5));
521 RELOC_ABS_FFFF (MEM_POS+2, 0);
524 | arith_inst '[' REG ']' ',' '#' expr {
525 size = find_size0(inst_size);
529 op[1] = reg_indirect($3) * 16 + arith_opcode;
530 op[2] = imm_data8($7);
531 RELOC_ABS_FF(MEM_POS+2, 0);
535 op[1] = reg_indirect($3) * 16 + arith_opcode;
536 op[2] = msb(imm_data16($7));
537 op[3] = lsb(imm_data16($7));
538 RELOC_ABS_FFFF (MEM_POS+2, 0);
541 | arith_inst '[' REG '+' ']' ',' '#' expr {
542 size = find_size0(inst_size);
546 op[1] = reg_indirect($3) * 16 + arith_opcode;
547 op[2] = imm_data8($8);
548 RELOC_ABS_FF(MEM_POS+2, 0);
552 op[1] = reg_indirect($3) * 16 + arith_opcode;
553 op[2] = msb(imm_data16($8));
554 op[3] = lsb(imm_data16($8));
555 RELOC_ABS_FFFF (MEM_POS+2, 0);
558 | arith_inst '[' REG '+' expr ']' ',' '#' expr {
559 size = find_size0(inst_size);
560 if ($5 >= -128 && $5 <= 127) {
564 op[1] = reg_indirect($3) * 16 + arith_opcode;
565 op[2] = ($5 >= 0) ? $5 : 256 + $5;
566 op[3] = imm_data8($9);
567 RELOC_ABS_FF(MEM_POS+2, 0);
568 RELOC_ABS_FF(MEM_POS+3, 1);
572 op[1] = reg_indirect($3) * 16 + arith_opcode;
573 op[2] = ($5 >= 0) ? $5 : 256 + $5;
574 op[3] = msb(imm_data16($9));
575 op[4] = lsb(imm_data16($9));
576 RELOC_ABS_FF(MEM_POS+2, 0);
577 RELOC_ABS_FFFF(MEM_POS+3, 1);
583 op[1] = reg_indirect($3) * 16 + arith_opcode;
584 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
585 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
586 op[4] = imm_data8($9);
587 RELOC_ABS_FFFF(MEM_POS+2,0);
588 RELOC_ABS_FF(MEM_POS+4,1);
592 op[1] = reg_indirect($3) * 16 + arith_opcode;
593 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
594 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
595 op[4] = msb(imm_data16($9));
596 op[5] = lsb(imm_data16($9));
597 RELOC_ABS_FFFF(MEM_POS+2, 0);
598 RELOC_ABS_FFFF(MEM_POS+4, 1);
602 | arith_inst WORD ',' '#' expr {
603 size = find_size0(inst_size);
607 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
608 op[2] = lsb(direct_addr($2));
609 op[3] = imm_data8($5);
610 RELOC_DIR_70FF(MEM_POS+1,0);
611 RELOC_ABS_FF(MEM_POS+3,1);
615 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
616 op[2] = lsb(direct_addr($2));
617 op[3] = msb(imm_data16($5));
618 op[4] = lsb(imm_data16($5));
619 RELOC_DIR_70FF(MEM_POS+1,0);
620 RELOC_ABS_FFFF (MEM_POS+3,1);
624 /* the next 8 instructions are MOV, but because MOV was used in the */
625 /* arith_inst group, it will cause a shift/reduce conflict if used */
626 /* directly below... so we're forced to use arith_inst and then */
627 /* add a bit of code to make sure it was MOV and not the other ones */
629 | arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
630 /* this addr mode is only valid for MOV */
631 if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
632 size = find_size0(inst_size);
634 op[0] = 0x90 + size * 8;
635 op[1] = reg_indirect($3) * 16 + reg_indirect($8);
637 | arith_inst WORD ',' '[' REG ']' {
638 /* this addr mode is only valid for MOV */
639 if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
640 size = find_size0(inst_size);
642 op[0] = 0xA0 + size * 8;
643 op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
644 op[2] = lsb(direct_addr($2));
645 RELOC_DIR_07FF(MEM_POS+1, 0);
647 | arith_inst '[' REG ']' ',' WORD {
648 /* this addr mode is only valid for MOV */
649 if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
650 size = find_size0(inst_size);
652 op[0] = 0xA0 + size * 8;
653 op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
654 op[2] = lsb(direct_addr($6));
655 RELOC_DIR_07FF(MEM_POS+1, 0);
657 | arith_inst WORD ',' WORD {
658 /* this addr mode is only valid for MOV */
659 if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
660 size = find_size0(inst_size);
662 op[0] = 0x97 + size * 8;
663 op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
664 op[2] = lsb(direct_addr($2));
665 op[3] = lsb(direct_addr($4));
666 RELOC_DIR_70FF(MEM_POS+1, 0);
667 RELOC_DIR_0700FF(MEM_POS+1, 1);
669 | arith_inst REG ',' USP {
670 /* this addr mode is only valid for MOV */
671 if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
674 op[1] = reg($2) * 16 + 15;
676 | arith_inst USP ',' REG {
677 /* this addr mode is only valid for MOV */
678 if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
681 op[1] = reg($4) * 16 + 15;
683 | arith_inst C ',' bit {
684 /* this addr mode is only valid for MOV */
685 if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
688 op[1] = 0x20 + msb(bit_addr($4));
689 op[2] = lsb(bit_addr($4));
690 RELOC_BIT_03FF(MEM_POS+1, 0);
692 | arith_inst bit ',' C {
693 /* this addr mode is only valid for MOV */
694 if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
697 op[1] = 0x30 + msb(bit_addr($2));
698 op[2] = lsb(bit_addr($2));
699 RELOC_BIT_03FF(MEM_POS+1, 0);
702 | MOVC REG ',' '[' REG '+' ']' {
703 size = find_size1(inst_size, $2);
705 op[0] = 0x80 + size * 8;
706 op[1] = reg($2) * 16 + reg_indirect($5);
708 | MOVC A ',' '[' A '+' DPTR ']' {
713 | MOVC A ',' '[' A '+' PC ']' {
718 | MOVX REG ',' '[' REG ']' {
720 size = find_size1(inst_size, $2);
721 op[0] = 0xA7 + size * 8;
722 op[1] = reg($2) * 16 + reg_indirect($5);
724 | MOVX '[' REG ']' ',' REG {
726 size = find_size1(inst_size, $6);
727 op[0] = 0xA7 + size * 8;
728 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
732 size = find_size2(inst_size, $2, $4);
733 op[0] = 0x60 + size * 8;
734 op[1] = reg($2) * 16 + reg($4);
736 | XCH REG ',' '[' REG ']' {
738 size = find_size1(inst_size, $2);
739 op[0] = 0x50 + size * 8;
740 op[1] = reg($2) * 16 + reg_indirect($5);
744 size = find_size1(inst_size, $2);
745 op[0] = 0xA0 + size * 8;
746 op[1] = reg($2) * 16 + msb(direct_addr($4));
747 op[2] = lsb(direct_addr($4));
748 RELOC_DIR_07FF(MEM_POS+1, 0);
750 | short_data_inst REG ',' '#' expr {
752 size = find_size1(inst_size, $2);
753 op[0] = short_opcode + size * 8 + 1;
754 op[1] = reg($2) * 16 + imm_data4_signed($5);
755 RELOC_ABS_0F(MEM_POS+1, 0);
757 | short_data_inst '[' REG ']' ',' '#' expr {
759 size = find_size0(inst_size);
760 op[0] = short_opcode + size * 8 + 2;
761 op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
762 RELOC_ABS_0F(MEM_POS+1, 0);
764 | short_data_inst '[' REG '+' ']' ',' '#' expr {
766 size = find_size0(inst_size);
767 op[0] = short_opcode + size * 8 + 3;
768 op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
769 RELOC_ABS_0F(MEM_POS+1, 0);
771 | short_data_inst '[' REG '+' expr ']' ',' '#' expr {
772 size = find_size0(inst_size);
773 if ($5 >= -128 && $5 <= 127) {
775 op[0] = short_opcode + size * 8 + 4;
776 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
777 op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
778 RELOC_ABS_0F(MEM_POS+1, 1);
779 RELOC_ABS_FF(MEM_POS+2, 0);
782 op[0] = short_opcode + size * 8 + 5;
783 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
784 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
785 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
786 RELOC_ABS_0F(MEM_POS+1, 1);
787 RELOC_ABS_FFFF(MEM_POS+2, 0);
790 | short_data_inst expr ',' '#' expr {
792 size = find_size0(inst_size);
793 op[0] = short_opcode + size * 8 + 6;
794 op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
795 op[2] = lsb(direct_addr($2));
796 RELOC_ABS_0F(MEM_POS+1, 0);
801 op[1] = 0x40 + msb(bit_addr($4));
802 op[2] = lsb(bit_addr($4));
803 RELOC_BIT_03FF(MEM_POS+1, 0);
805 | ANL C ',' '/' bit {
808 op[1] = 0x50 + msb(bit_addr($5));
809 op[2] = lsb(bit_addr($5));
810 RELOC_BIT_03FF(MEM_POS+1, 0);
816 op[1] = 0x60 + msb(bit_addr($4));
817 op[2] = lsb(bit_addr($4));
818 RELOC_BIT_03FF(MEM_POS+1, 0);
820 | ORL C ',' '/' bit {
823 op[1] = 0x70 + msb(bit_addr($5));
824 op[2] = lsb(bit_addr($5));
825 RELOC_BIT_03FF(MEM_POS+1, 0);
830 op[1] = msb(bit_addr($2));
831 op[2] = lsb(bit_addr($2));
832 RELOC_BIT_03FF(MEM_POS+1, 0);
837 op[1] = 0x10 + msb(bit_addr($2));
838 op[2] = lsb(bit_addr($2));
839 RELOC_BIT_03FF(MEM_POS+1, 0);
841 | logical_shift_inst REG ',' REG {
842 size = find_size1(inst_size, $2);
843 if (find_size_reg($4) != SIZE8)
844 error("Second register in logical shift must be byte size");
846 op[0] = shift_reg_opcode;
848 case SIZE8: op[0] += 0; break;
849 case SIZE16: op[0] += 8; break;
850 case SIZE32: op[0] += 12; break;
852 op[1] = reg($2) * 16 + reg($4);
854 | logical_shift_inst REG ',' '#' NUMBER {
855 size = find_size1(inst_size, $2);
857 if (shift_imm_opcode == -1)
858 error("NORM may not use a constant");
859 op[0] = shift_imm_opcode;
861 case SIZE8: op[0] += 0; break;
862 case SIZE16: op[0] += 8; break;
863 case SIZE32: op[0] += 12; break;
868 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
871 op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
884 op[1] = 0x30 + imm_data4_unsigned($3);
888 size = find_size1(inst_size, $2);
889 op[0] = 0x90 + size * 8;
890 op[1] = reg($2) * 16 + 10;
895 op[1] = reg($2) * 16 + 8;
899 size = find_size1(inst_size, $2);
900 op[0] = 0x90 + size * 8;
901 op[1] = reg($2) * 16 + 11;
905 size = find_size1(inst_size, $2);
906 op[0] = 0x90 + size * 8;
907 op[1] = reg($2) * 16 + 9;
910 | rotate_inst REG ',' '#' NUMBER {
912 size = find_size1(inst_size, $2);
913 op[0] = rotate_opcode + size * 8;
914 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
918 | LEA REG ',' REG '+' expr {
919 if ($6 >= -128 && $6 <= 127) {
922 op[1] = reg($2) * 16 + reg_indirect($4);
923 op[2] = ($6 >= 0) ? $6 : 256 + $6;
924 RELOC_ABS_FF(MEM_POS+2, 0);
927 op[1] = reg($2) * 16 + reg_indirect($4);
928 op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
929 op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
930 RELOC_ABS_FFFF(MEM_POS+2, 0);
935 size = find_size0(inst_size);
936 op[0] = msb(stack_addr_opcode) + size * 8;
937 op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
938 op[2] = lsb(direct_addr($2));
939 RELOC_DIR_07FF(MEM_POS+1, 0);
943 if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
944 error("inst specifies different size than registers used");
945 op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
946 op[1] = rlist_bitmask;
952 size = find_size2(inst_size, $2, $4);
954 op[1] = reg($2) * 16 + reg($4);
958 size = find_size2(inst_size, $2, $4);
961 op[1] = reg($2) * 16 + reg($4);
964 op[1] = reg($2) * 16 + reg($4);
967 | MUL REG ',' '#' expr {
969 size = find_size1(inst_size, $2);
972 op[2] = msb(imm_data16($5));
973 op[3] = lsb(imm_data16($5));
974 RELOC_ABS_FFFF(MEM_POS+2, 0);
976 | MULU REG ',' '#' expr {
977 size = find_size2(inst_size, $2, $4);
981 op[1] = reg($2) * 16;
982 op[2] = imm_data8($5);
983 RELOC_ABS_FF(MEM_POS+2, 0);
987 op[1] = reg($2) * 16;
988 op[2] = msb(imm_data16($5));
989 op[3] = lsb(imm_data16($5));
990 RELOC_ABS_FFFF(MEM_POS+2, 0);
995 size = find_size2(inst_size, $2, $4);
998 error("Signed DIV can't be 8 bit size"); break;
1001 op[1] = reg($2) * 16 + reg($4);
1005 op[1] = (reg($2) / 2) * 32 + reg($4);
1009 | DIVU REG ',' REG {
1011 size = find_size2(inst_size, $2, $4);
1015 op[1] = reg($2) * 16 + reg($4);
1019 op[1] = reg($2) * 16 + reg($4);
1023 op[1] = (reg($2) / 2) * 32 + reg($4);
1027 | DIV REG ',' '#' expr {
1028 size = find_size1(inst_size, $2);
1031 error("Singed DIV can't be 8 bit size"); break;
1035 op[1] = reg($2) * 16 + 11;
1036 op[2] = imm_data8($5);
1037 RELOC_ABS_FF(MEM_POS+2, 0);
1042 op[1] = (reg($2) / 2) * 32 + 9;
1043 op[2] = msb(imm_data16($5));
1044 op[3] = lsb(imm_data16($5));
1045 RELOC_ABS_FFFF(MEM_POS+2, 0);
1049 | DIVU REG ',' '#' expr {
1050 size = find_size1(inst_size, $2);
1055 op[1] = reg($2) * 16 + 1;
1056 op[2] = imm_data8($5);
1057 RELOC_ABS_FF(MEM_POS+2, 0);
1062 op[1] = reg($2) * 16 + 3;
1063 op[2] = imm_data8($5);
1064 RELOC_ABS_FF(MEM_POS+2, 0);
1069 op[1] = (reg($2) / 2) * 32 + 1;
1070 op[2] = msb(imm_data16($5));
1071 op[3] = lsb(imm_data16($5));
1072 RELOC_ABS_FFFF(MEM_POS+2, 0);
1076 | CALL '[' REG ']' {
1084 op[1] = ($2 >> 8) & 255;
1086 op[3] = ($2 >> 16) & 255;
1091 op[1] = ($2 >> 8) & 255;
1093 op[3] = ($2 >> 16) & 255;
1098 op[1] = 0x70 + reg_indirect($3);
1100 | JMP '[' A '+' DPTR ']' {
1105 | JMP '[' '[' REG '+' ']' ']' {
1108 op[1] = 0x60 + reg_indirect($4);
1114 op[1] = msb(rel16(MEM_POS + $$, $2));
1115 op[2] = lsb(rel16(MEM_POS + $$, $2));
1116 RELOC_FFFF(MEM_POS+1,MEM_POS+$$,0);
1122 op[1] = msb(rel16(MEM_POS + $$, $2));
1123 op[2] = lsb(rel16(MEM_POS + $$, $2));
1124 RELOC_FFFF(MEM_POS+1, MEM_POS+$$, 0);
1126 | branch_inst jmpaddr {
1128 op[0] = branch_opcode;
1129 op[1] = rel8(MEM_POS + $$, $2);
1130 RELOC_FF(MEM_POS+1,MEM_POS + $$, 0);
1132 | CJNE REG ',' expr ',' jmpaddr {
1134 size = find_size1(inst_size, $2);
1135 op[0] = 0xE2 + size * 8;
1136 op[1] = reg($2) * 16 + msb(direct_addr($4));
1137 op[2] = lsb(direct_addr($4));
1138 op[3] = rel8(MEM_POS + $$, $6);
1139 RELOC_DIR_07FF(MEM_POS+1, 0);
1140 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1142 | CJNE REG ',' '#' expr ',' jmpaddr {
1143 size = find_size1(inst_size, $2);
1144 if (size == SIZE8) {
1147 op[1] = reg($2) * 16;
1148 op[2] = rel8(MEM_POS + $$, $7);
1149 op[3] = imm_data8($5);
1150 RELOC_ABS_FF(MEM_POS+3, 0);
1154 op[1] = reg($2) * 16;
1155 op[2] = rel8(MEM_POS + $$, $7);
1156 op[3] = msb(imm_data16($5));
1157 op[4] = lsb(imm_data16($5));
1158 RELOC_ABS_FFFF(MEM_POS+3, 0);
1161 | CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
1162 size = find_size0(inst_size);
1163 if (size == SIZE8) {
1166 op[1] = reg_indirect($3) * 16 + 8;
1167 op[2] = rel8(MEM_POS + $$, $9);
1168 op[3] = imm_data8($7);
1169 RELOC_ABS_FF(MEM_POS+3, 0);
1173 op[1] = reg_indirect($3) * 16 + 8;
1174 op[2] = rel8(MEM_POS + $$, $9);
1175 op[3] = msb(imm_data16($7));
1176 op[4] = lsb(imm_data16($7));
1177 RELOC_ABS_FFFF(MEM_POS+3, 0);
1180 | DJNZ REG ',' jmpaddr {
1182 size = find_size1(inst_size, $2);
1183 op[0] = 0x87 + size * 8;
1184 op[1] = reg($2) * 16 + 8;
1185 op[2] = rel8(MEM_POS + $$, $4);
1186 RELOC_FF(MEM_POS+2, MEM_POS+$$, 0);
1190 | DJNZ WORD ',' jmpaddr {
1192 size = find_size0(inst_size);
1193 op[0] = 0xE2 + size * 8;
1194 op[1] = msb(direct_addr($2)) + 8;
1195 op[2] = lsb(direct_addr($2));
1196 op[3] = rel8(MEM_POS + $$, $4);
1197 RELOC_DIR_07FF(MEM_POS+1, 0);
1198 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1)
1201 | JB bit ',' jmpaddr {
1204 op[1] = 0x80 + msb(bit_addr($2));
1205 op[2] = lsb(bit_addr($2));
1206 op[3] = rel8(MEM_POS + $$, $4);
1207 RELOC_BIT_03FF(MEM_POS+1, 0);
1208 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1211 | JBC bit ',' jmpaddr {
1214 op[1] = 0xC0 + msb(bit_addr($2));
1215 op[2] = lsb(bit_addr($2));
1216 op[3] = rel8(MEM_POS + $$, $4);
1217 RELOC_BIT_03FF(MEM_POS+1, 0);
1218 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1221 | JNB bit ',' jmpaddr {
1224 op[1] = 0xA0 + msb(bit_addr($2));
1225 op[2] = lsb(bit_addr($2));
1226 op[3] = rel8(MEM_POS + $$, $4);
1227 RELOC_BIT_03FF(MEM_POS+1, 0);
1228 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1233 ADD {arith_opcode = 0;}
1234 | ADDC {arith_opcode = 1;}
1235 | AND {arith_opcode = 5;}
1236 | CMP {arith_opcode = 4;}
1237 | MOV {arith_opcode = 8;}
1238 | OR {arith_opcode = 6;}
1239 | SUB {arith_opcode = 2;}
1240 | SUBB {arith_opcode = 3;}
1241 | XOR {arith_opcode = 7;}
1244 ADDS {short_opcode = 0xA0;}
1245 | MOVS {short_opcode = 0xB0;}
1248 ASL {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
1249 | ASR {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
1250 | LSR {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
1251 | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
1254 RL {rotate_opcode = 0xD3;}
1255 | RLC {rotate_opcode = 0xD7;}
1256 | RR {rotate_opcode = 0xD0;}
1257 | RRC {rotate_opcode = 0xD7;}
1260 POP {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
1261 | POPU {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
1262 | PUSH {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
1263 | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
1266 BKPT {num_op = 1; opcode0 = 255; opcode1 = 0;}
1267 | NOP {num_op = 1; opcode0 = 0; opcode1 = 0;}
1268 | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
1269 | RET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
1270 | RETI {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
1273 BCC {branch_opcode = 0xF0;}
1274 | BCS {branch_opcode = 0xF1;}
1275 | BEQ {branch_opcode = 0xF3;}
1276 | BG {branch_opcode = 0xF8;}
1277 | BGE {branch_opcode = 0xFA;}
1278 | BGT {branch_opcode = 0xFC;}
1279 | BL {branch_opcode = 0xF9;}
1280 | BLE {branch_opcode = 0xFD;}
1281 | BLT {branch_opcode = 0xFB;}
1282 | BMI {branch_opcode = 0xF7;}
1283 | BNE {branch_opcode = 0xF2;}
1284 | BNV {branch_opcode = 0xF4;}
1285 | BOV {branch_opcode = 0xF5;}
1286 | BPL {branch_opcode = 0xF6;}
1287 | BR {branch_opcode = 0xFE;}
1288 | JZ {branch_opcode = 0xEC;}
1289 | JNZ {branch_opcode = 0xEE;}
1296 int reg(int reg_spec)
1298 return reg_spec & 15;
1301 int reg_indirect(int reg_spec)
1303 if (reg_spec & BYTE_REG)
1304 error("Indirect addressing may not use byte registers");
1305 if ((reg_spec & 15) > 7)
1306 error("Only R0 through R7 may be used for indirect addr");
1307 return reg_spec & 7;
1310 int rel16(int pos, int dest)
1314 if (!p3) return 0; /* don't bother unless writing code */
1315 if (dest & (BRANCH_SPACING - 1))
1316 error("Attempt to jump to unaligned location");
1317 pos &= ~(BRANCH_SPACING - 1);
1318 rel = (dest - pos) / BRANCH_SPACING;
1319 if (rel < -32768 || rel > 32767)
1320 error("Attempt to jump out of 16 bit relative range");
1321 if (rel < 0) rel += 65536;
1325 int rel8(int pos, int dest)
1329 if (!p3) return 0; /* don't bother unless writing code */
1330 if (dest & (BRANCH_SPACING - 1))
1331 error("Attempt to jump to unaligned location");
1332 pos &= ~(BRANCH_SPACING - 1);
1333 rel = (dest - pos) / BRANCH_SPACING;
1334 if (rel < -128 || rel > 127)
1335 error("Attempt to jump out of 16 bit relative range");
1336 if (rel < 0) rel += 256;
1342 return (value >> 8) & 255;
1350 int direct_addr(int value)
1354 if (value < 0 || value > 2047) {
1355 sprintf(buf, "illegal value (%d) for direct address", value);
1361 int imm_data4_signed(int value)
1363 if (value < -8 || value > 7)
1364 error("illegal 4 bit (signed) value");
1365 if (value >= 0) return value;
1366 else return (16 + value);
1369 int imm_data4_unsigned(int value)
1371 if (value < 0 || value > 15)
1372 error("illegal 4 bit (unsigned) value");
1376 int imm_data5_unsigned(int value)
1378 if (value < 0 || value > 31)
1379 error("illegal 5 bit (unsigned) value");
1383 int imm_data8(int value)
1385 if (value < -128 || value > 255)
1386 error("illegal 8 bit value");
1387 if (value >= 0) return value;
1388 else return (256 + value);
1391 int imm_data16(int value)
1393 if (value < -32728 || value > 65535)
1394 error("illegal 16 bit value");
1395 if (value >= 0) return value;
1396 else return (65536 + value);
1399 int bit_addr(int value)
1401 if (value < 0 || value > 1023) {
1402 fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
1404 error("illegal bit address");
1410 int find_size_reg(int op1spec)
1412 int op1size=UNKNOWN;
1414 if (op1spec & BYTE_REG) op1size = SIZE8;
1415 if (op1spec & WORD_REG) op1size = SIZE16;
1416 if (op1size == UNKNOWN)
1417 error("Register without implied size");
1421 int find_size0(int isize)
1423 if (isize == UNKNOWN)
1424 error("Can't determine data size from instruction");
1428 int find_size1(int isize, int op1spec)
1430 int op1size=UNKNOWN;
1432 if (op1spec & BYTE_REG) op1size = SIZE8;
1433 if (op1spec & WORD_REG) op1size = SIZE16;
1434 if (op1size == UNKNOWN)
1435 error("Register without implied size");
1437 if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
1438 if (isize == UNKNOWN) return op1size;
1440 if (isize != op1size)
1441 error("data size of register and inst don't agree");
1446 int find_size2(int isize, int op1spec, int op2spec)
1448 int op1size=UNKNOWN, op2size=UNKNOWN;
1450 if (op1spec & BYTE_REG) op1size = SIZE8;
1451 if (op1spec & WORD_REG) op1size = SIZE16;
1452 if (op1size == UNKNOWN)
1453 error("Register without implied size");
1454 if (op2spec & BYTE_REG) op2size = SIZE8;
1455 if (op2spec & WORD_REG) op2size = SIZE16;
1456 if (op1size == UNKNOWN)
1457 error("Register without implied size");
1459 if (op1size != op2size)
1460 error("data sizes of two registers don't agree");
1461 if (isize == UNKNOWN) return op1size;
1463 if (isize != op1size)
1464 error("data size of registers and inst don't agree");
1469 int yyerror(char *s)
1471 if (yytext[0] >= 32) {
1472 fprintf(stderr, "%s near '%s', line %d\n",
1475 fprintf(stderr, "%s, line %d\n", s, lineno - 1);