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');
173 linenosym: directive EOL {
182 if (p3) out(NULL, 0);
185 | error EOL /* try to recover from any parse error */
188 directive: '.' ORG expr {
196 | '.' EQU symbol ',' expr {
197 if (p1) build_sym_list(symbol_name);
198 if (p1 || p2) assign_value(symbol_name, $5, '?');
202 if (p1) build_sym_list(symbol_name);
203 if (p1 || p2) assign_value(symbol_name, $3, '=');
206 if (p1) build_sym_list(symbol_name);
207 if (p1 || p2) assign_value(symbol_name, $3, 'A');
208 if (p1 || p2) mk_sfr(symbol_name);
211 | '.' BITDEF bitsymbol ',' bit {
213 build_sym_list(symbol_name);
214 mk_bit(symbol_name, 0);
216 if (p1 || p2) assign_value(symbol_name, $5, '?');
219 | bitsymbol BITDEF bit {
221 build_sym_list(symbol_name);
222 mk_bit(symbol_name, 0);
224 if (p1 || p2) assign_value(symbol_name, $3, '?');
227 | bitsymbol BITDEF expr {
229 build_sym_list(symbol_name);
230 mk_bit(symbol_name, 0);
232 if (p1 || p2) assign_value(symbol_name, $3, 'A');
235 | '.' REGDEF regsymbol ',' REG {
237 build_sym_list(symbol_name);
240 if (p1 || p2) assign_value(symbol_name, $5, '?');
243 | regsymbol REGDEF REG {
245 build_sym_list(symbol_name);
248 if (p1 || p2) assign_value(symbol_name, $3, '?');
252 | '.' db_directive bytes {
255 | '.' dw_directive words {
258 | '.' AREA AREA_NAME AREA_DESC {
259 if ($3 < 0 || $3 > NUM_AREAS) {
260 error("Illegal Area Directive");
262 symbol_name[0] = '\0';
267 /* ignore module definition */
271 mk_global(lex_sym_name);
272 /* ignore global symbol declaration */
276 /* ignore bit symbol declaration */
280 /* todo: if CSEG, emit some filler bytes */
284 db_directive: DB {db_count = 0;}
287 linesymbol: normal_or_bit_symbol {
288 strcpy(symbol_name, lex_sym_name);
289 if (!strchr(lex_sym_name, ':')) {
290 /* non-local label, remember base name */
291 strcpy(base_symbol_name, lex_sym_name);
293 if (is_target(symbol_name)) pad_with_nop();
296 normal_or_bit_symbol: WORD {$$ = $1;}
300 | bytes ',' byte_element
303 op[db_count] = $1 & 255;
304 if (++db_count >= MAX_DB) {
305 error("too many bytes, use two DB");
310 for(i=1; i < strlen(yytext)-1; i++) {
311 op[db_count++] = yytext[i];
312 if (db_count >= MAX_DB) {
313 error("too many bytes, use two DB");
319 dw_directive: DW {dw_count = 0;}
321 words: words ',' word_element
325 op[dw_count] = $1 & 255;
326 op[dw_count+1] = ($1 >> 8) & 255;
328 if (dw_count >= MAX_DB) {
329 error("too many bytes, use two DW");
337 strcpy(symbol_name, lex_sym_name);
340 bitsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
341 | BIT { strcpy(symbol_name, lex_sym_name); }
344 regsymbol: WORD { strcpy(symbol_name, lex_sym_name); }
345 | REG { strcpy(symbol_name, lex_sym_name); }
348 if ($3 < 0 || $3 > 7) {
349 /* only 8 bits in a byte */
350 error("Only eight bits in a byte");
352 $$ = 100000; /* should really check $1 is valid */
353 if ($1 >= 0x20 && $1 <= 0x3F) {
356 if ($1 >= 0x400 && $1 <= 0x43F) {
357 $$ = ($1 - 0x400) * 8 + $3 + 0x200;
362 if (find_size_reg($1) == SIZE8) {
363 if ($3 < 0 || $3 > 7)
364 error("byte reg has only 8 bits");
365 $$ = reg($1) * 8 + $3;
367 if (find_size_reg($1) == SIZE16) {
368 if ($3 < 0 || $3 > 15)
369 error("word reg has only 16 bits");
370 $$ = reg($1) * 16 + $3;
377 if (p1) build_target_list(lex_sym_name);
380 if ($1 & 1) error("Jump target must be aligned");
385 expr: value {$$ = $1;}
386 | expr '+' expr {$$ = $1 + $3;}
387 | expr '-' expr {$$ = $1 - $3;}
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 RSHIFT expr {$$ = $1 >> $3;}
394 | expr LSHIFT expr {$$ = $1 << $3;}
395 | '-' expr %prec UNARY {$$ = $2 * -1;}
396 | '+' expr %prec UNARY {$$ = $2;}
397 | '(' expr ')' {$$ = $2;}
398 | LOW expr %prec UNARY {$$ = $2 & 255;}
399 | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
402 value: NUMBER {$$ = $1;}
407 rlist_bitmask = 1<<(reg($1) % 8);
408 rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
409 rlist_size = find_size_reg($1);
412 rlist_bitmask |= 1<<(reg($1) % 8);
413 if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
414 error("register list may not mix 0-7/8-15 regs");
415 if (rlist_size != find_size_reg($1))
416 error("register list may not mix 8/16 bit registers");
425 arith_inst REG ',' REG {
427 size = find_size2(inst_size, $2, $4);
428 op[0] = arith_opcode * 16 + size * 8 + 1;
429 op[1] = reg($2) * 16 + reg($4);
431 | arith_inst REG ',' '[' REG ']' {
433 size = find_size1(inst_size, $2);
434 op[0] = arith_opcode * 16 + size * 8 + 2;
435 op[1] = reg($2) * 16 + reg_indirect($5);
437 | arith_inst '[' REG ']' ',' REG {
439 size = find_size1(inst_size, $6);
440 op[0] = arith_opcode * 16 + size * 8 + 2;
441 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
443 | arith_inst REG ',' '[' REG '+' expr ']' {
444 size = find_size1(inst_size, $2);
445 if ($7 >= -128 && $7 <= 127) {
447 op[0] = arith_opcode * 16 + size * 8 + 4;
448 op[1] = reg($2) * 16 + reg_indirect($5);
449 op[2] = ($7 >= 0) ? $7 : 256 + $7;
450 RELOC_ABS_FF(MEM_POS+2,0);
453 op[0] = arith_opcode * 16 + size * 8 + 5;
454 op[1] = reg($2) * 16 + reg_indirect($5);
455 op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
456 op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
457 RELOC_ABS_FFFF(MEM_POS+2,0);
460 | arith_inst '[' REG '+' expr ']' ',' REG {
461 size = find_size1(inst_size, $8);
462 if ($5 >= -128 && $5 <= 127) {
464 op[0] = arith_opcode * 16 + size * 8 + 4;
465 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
466 op[2] = ($5 >= 0) ? $5 : 256 + $5;
467 RELOC_ABS_FF(MEM_POS+2,0);
470 op[0] = arith_opcode * 16 + size * 8 + 5;
471 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
472 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
473 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
474 RELOC_ABS_FFFF(MEM_POS+2,0);
477 | arith_inst REG ',' '[' REG '+' ']' {
479 size = find_size1(inst_size, $2);
480 op[0] = arith_opcode * 16 + size * 8 + 3;
481 op[1] = reg($2) * 16 + reg_indirect($5);
483 | arith_inst '[' REG '+' ']' ',' REG {
485 size = find_size1(inst_size, $7);
486 op[0] = arith_opcode * 16 + size * 8 + 3;
487 op[1] = reg($7) * 16 + 8 + reg_indirect($3);
489 | arith_inst WORD ',' REG {
491 size = find_size1(inst_size, $4);
492 op[0] = arith_opcode * 16 + size * 8 + 6;
493 op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
494 op[2] = lsb(direct_addr($2));
495 RELOC_DIR_07FF(MEM_POS+1, 0);
497 | arith_inst REG ',' WORD {
499 size = find_size1(inst_size, $2);
500 op[0] = arith_opcode * 16 + size * 8 + 6;
501 op[1] = reg($2) * 16 + msb(direct_addr($4));
502 op[2] = lsb(direct_addr($4));
503 RELOC_DIR_07FF(MEM_POS+1, 0);
505 | arith_inst REG ',' '#' expr {
506 size = find_size1(inst_size, $2);
510 op[1] = reg($2) * 16 + arith_opcode;
511 op[2] = imm_data8($5);
512 RELOC_ABS_FF(MEM_POS+2, 0);
516 op[1] = reg($2) * 16 + arith_opcode;
517 op[2] = msb(imm_data16($5));
518 op[3] = lsb(imm_data16($5));
519 RELOC_ABS_FFFF (MEM_POS+2, 0);
522 | arith_inst '[' REG ']' ',' '#' expr {
523 size = find_size0(inst_size);
527 op[1] = reg_indirect($3) * 16 + arith_opcode;
528 op[2] = imm_data8($7);
529 RELOC_ABS_FF(MEM_POS+2, 0);
533 op[1] = reg_indirect($3) * 16 + arith_opcode;
534 op[2] = msb(imm_data16($7));
535 op[3] = lsb(imm_data16($7));
536 RELOC_ABS_FFFF (MEM_POS+2, 0);
539 | arith_inst '[' REG '+' ']' ',' '#' expr {
540 size = find_size0(inst_size);
544 op[1] = reg_indirect($3) * 16 + arith_opcode;
545 op[2] = imm_data8($8);
546 RELOC_ABS_FF(MEM_POS+2, 0);
550 op[1] = reg_indirect($3) * 16 + arith_opcode;
551 op[2] = msb(imm_data16($8));
552 op[3] = lsb(imm_data16($8));
553 RELOC_ABS_FFFF (MEM_POS+2, 0);
556 | arith_inst '[' REG '+' expr ']' ',' '#' expr {
557 size = find_size0(inst_size);
558 if ($5 >= -128 && $5 <= 127) {
562 op[1] = reg_indirect($3) * 16 + arith_opcode;
563 op[2] = ($5 >= 0) ? $5 : 256 + $5;
564 op[3] = imm_data8($9);
565 RELOC_ABS_FF(MEM_POS+2, 0);
566 RELOC_ABS_FF(MEM_POS+3, 1);
570 op[1] = reg_indirect($3) * 16 + arith_opcode;
571 op[2] = ($5 >= 0) ? $5 : 256 + $5;
572 op[3] = msb(imm_data16($9));
573 op[4] = lsb(imm_data16($9));
574 RELOC_ABS_FF(MEM_POS+2, 0);
575 RELOC_ABS_FFFF(MEM_POS+3, 1);
581 op[1] = reg_indirect($3) * 16 + arith_opcode;
582 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
583 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
584 op[4] = imm_data8($9);
585 RELOC_ABS_FFFF(MEM_POS+2,0);
586 RELOC_ABS_FF(MEM_POS+4,1);
590 op[1] = reg_indirect($3) * 16 + arith_opcode;
591 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
592 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
593 op[4] = msb(imm_data16($9));
594 op[5] = lsb(imm_data16($9));
595 RELOC_ABS_FFFF(MEM_POS+2, 0);
596 RELOC_ABS_FFFF(MEM_POS+4, 1);
600 | arith_inst WORD ',' '#' expr {
601 size = find_size0(inst_size);
605 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
606 op[2] = lsb(direct_addr($2));
607 op[3] = imm_data8($5);
608 RELOC_DIR_70FF(MEM_POS+1,0);
609 RELOC_ABS_FF(MEM_POS+3,1);
613 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
614 op[2] = lsb(direct_addr($2));
615 op[3] = msb(imm_data16($5));
616 op[4] = lsb(imm_data16($5));
617 RELOC_DIR_70FF(MEM_POS+1,0);
618 RELOC_ABS_FFFF (MEM_POS+3,1);
622 /* the next 8 instructions are MOV, but because MOV was used in the */
623 /* arith_inst group, it will cause a shift/reduce conflict if used */
624 /* directly below... so we're forced to use arith_inst and then */
625 /* add a bit of code to make sure it was MOV and not the other ones */
627 | arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
628 /* this addr mode is only valid for MOV */
629 if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
630 size = find_size0(inst_size);
632 op[0] = 0x90 + size * 8;
633 op[1] = reg_indirect($3) * 16 + reg_indirect($8);
635 | arith_inst WORD ',' '[' REG ']' {
636 /* this addr mode is only valid for MOV */
637 if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
638 size = find_size0(inst_size);
640 op[0] = 0xA0 + size * 8;
641 op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
642 op[2] = lsb(direct_addr($2));
643 RELOC_DIR_07FF(MEM_POS+1, 0);
645 | arith_inst '[' REG ']' ',' WORD {
646 /* this addr mode is only valid for MOV */
647 if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
648 size = find_size0(inst_size);
650 op[0] = 0xA0 + size * 8;
651 op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
652 op[2] = lsb(direct_addr($6));
653 RELOC_DIR_07FF(MEM_POS+1, 0);
655 | arith_inst WORD ',' WORD {
656 /* this addr mode is only valid for MOV */
657 if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
658 size = find_size0(inst_size);
660 op[0] = 0x97 + size * 8;
661 op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
662 op[2] = lsb(direct_addr($2));
663 op[3] = lsb(direct_addr($4));
664 RELOC_DIR_70FF(MEM_POS+1, 0);
665 RELOC_DIR_0700FF(MEM_POS+1, 1);
667 | arith_inst REG ',' USP {
668 /* this addr mode is only valid for MOV */
669 if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
672 op[1] = reg($2) * 16 + 15;
674 | arith_inst USP ',' REG {
675 /* this addr mode is only valid for MOV */
676 if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
679 op[1] = reg($4) * 16 + 15;
681 | arith_inst C ',' bit {
682 /* this addr mode is only valid for MOV */
683 if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
686 op[1] = 0x20 + msb(bit_addr($4));
687 op[2] = lsb(bit_addr($4));
688 RELOC_BIT_03FF(MEM_POS+1, 0);
690 | arith_inst bit ',' C {
691 /* this addr mode is only valid for MOV */
692 if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
695 op[1] = 0x30 + msb(bit_addr($2));
696 op[2] = lsb(bit_addr($2));
697 RELOC_BIT_03FF(MEM_POS+1, 0);
700 | MOVC REG ',' '[' REG '+' ']' {
701 size = find_size1(inst_size, $2);
703 op[0] = 0x80 + size * 8;
704 op[1] = reg($2) * 16 + reg_indirect($5);
706 | MOVC A ',' '[' A '+' DPTR ']' {
711 | MOVC A ',' '[' A '+' PC ']' {
716 | MOVX REG ',' '[' REG ']' {
718 size = find_size1(inst_size, $2);
719 op[0] = 0xA7 + size * 8;
720 op[1] = reg($2) * 16 + reg_indirect($5);
722 | MOVX '[' REG ']' ',' REG {
724 size = find_size1(inst_size, $6);
725 op[0] = 0xA7 + size * 8;
726 op[1] = reg($6) * 16 + 8 + reg_indirect($3);
730 size = find_size2(inst_size, $2, $4);
731 op[0] = 0x60 + size * 8;
732 op[1] = reg($2) * 16 + reg($4);
734 | XCH REG ',' '[' REG ']' {
736 size = find_size1(inst_size, $2);
737 op[0] = 0x50 + size * 8;
738 op[1] = reg($2) * 16 + reg_indirect($5);
742 size = find_size1(inst_size, $2);
743 op[0] = 0xA0 + size * 8;
744 op[1] = reg($2) * 16 + msb(direct_addr($4));
745 op[2] = lsb(direct_addr($4));
746 RELOC_DIR_07FF(MEM_POS+1, 0);
748 | short_data_inst REG ',' '#' expr {
750 size = find_size1(inst_size, $2);
751 op[0] = short_opcode + size * 8 + 1;
752 op[1] = reg($2) * 16 + imm_data4_signed($5);
753 RELOC_ABS_0F(MEM_POS+1, 0);
755 | short_data_inst '[' REG ']' ',' '#' expr {
757 size = find_size0(inst_size);
758 op[0] = short_opcode + size * 8 + 2;
759 op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
760 RELOC_ABS_0F(MEM_POS+1, 0);
762 | short_data_inst '[' REG '+' ']' ',' '#' expr {
764 size = find_size0(inst_size);
765 op[0] = short_opcode + size * 8 + 3;
766 op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
767 RELOC_ABS_0F(MEM_POS+1, 0);
769 | short_data_inst '[' REG '+' expr ']' ',' '#' expr {
770 size = find_size0(inst_size);
771 if ($5 >= -128 && $5 <= 127) {
773 op[0] = short_opcode + size * 8 + 4;
774 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
775 op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
776 RELOC_ABS_0F(MEM_POS+1, 1);
777 RELOC_ABS_FF(MEM_POS+2, 0);
780 op[0] = short_opcode + size * 8 + 5;
781 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
782 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
783 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
784 RELOC_ABS_0F(MEM_POS+1, 1);
785 RELOC_ABS_FFFF(MEM_POS+2, 0);
788 | short_data_inst expr ',' '#' expr {
790 size = find_size0(inst_size);
791 op[0] = short_opcode + size * 8 + 6;
792 op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
793 op[2] = lsb(direct_addr($2));
794 RELOC_ABS_0F(MEM_POS+1, 0);
799 op[1] = 0x40 + msb(bit_addr($4));
800 op[2] = lsb(bit_addr($4));
801 RELOC_BIT_03FF(MEM_POS+1, 0);
803 | ANL C ',' '/' bit {
806 op[1] = 0x50 + msb(bit_addr($5));
807 op[2] = lsb(bit_addr($5));
808 RELOC_BIT_03FF(MEM_POS+1, 0);
814 op[1] = 0x60 + msb(bit_addr($4));
815 op[2] = lsb(bit_addr($4));
816 RELOC_BIT_03FF(MEM_POS+1, 0);
818 | ORL C ',' '/' bit {
821 op[1] = 0x70 + msb(bit_addr($5));
822 op[2] = lsb(bit_addr($5));
823 RELOC_BIT_03FF(MEM_POS+1, 0);
828 op[1] = msb(bit_addr($2));
829 op[2] = lsb(bit_addr($2));
830 RELOC_BIT_03FF(MEM_POS+1, 0);
835 op[1] = 0x10 + msb(bit_addr($2));
836 op[2] = lsb(bit_addr($2));
837 RELOC_BIT_03FF(MEM_POS+1, 0);
839 | logical_shift_inst REG ',' REG {
840 size = find_size1(inst_size, $2);
841 if (find_size_reg($4) != SIZE8)
842 error("Second register in logical shift must be byte size");
844 op[0] = shift_reg_opcode;
846 case SIZE8: op[0] += 0; break;
847 case SIZE16: op[0] += 8; break;
848 case SIZE32: op[0] += 12; break;
850 op[1] = reg($2) * 16 + reg($4);
852 | logical_shift_inst REG ',' '#' NUMBER {
853 size = find_size1(inst_size, $2);
855 if (shift_imm_opcode == -1)
856 error("NORM may not use a constant");
857 op[0] = shift_imm_opcode;
859 case SIZE8: op[0] += 0; break;
860 case SIZE16: op[0] += 8; break;
861 case SIZE32: op[0] += 12; break;
866 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
869 op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
882 op[1] = 0x30 + imm_data4_unsigned($3);
886 size = find_size1(inst_size, $2);
887 op[0] = 0x90 + size * 8;
888 op[1] = reg($2) * 16 + 10;
893 op[1] = reg($2) * 16 + 8;
897 size = find_size1(inst_size, $2);
898 op[0] = 0x90 + size * 8;
899 op[1] = reg($2) * 16 + 11;
903 size = find_size1(inst_size, $2);
904 op[0] = 0x90 + size * 8;
905 op[1] = reg($2) * 16 + 9;
908 | rotate_inst REG ',' '#' NUMBER {
910 size = find_size1(inst_size, $2);
911 op[0] = rotate_opcode + size * 8;
912 op[1] = reg($2) * 16 + imm_data4_unsigned($5);
916 | LEA REG ',' REG '+' expr {
917 if ($6 >= -128 && $6 <= 127) {
920 op[1] = reg($2) * 16 + reg_indirect($4);
921 op[2] = ($6 >= 0) ? $6 : 256 + $6;
922 RELOC_ABS_FF(MEM_POS+2, 0);
925 op[1] = reg($2) * 16 + reg_indirect($4);
926 op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
927 op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
928 RELOC_ABS_FFFF(MEM_POS+2, 0);
933 size = find_size0(inst_size);
934 op[0] = msb(stack_addr_opcode) + size * 8;
935 op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
936 op[2] = lsb(direct_addr($2));
937 RELOC_DIR_07FF(MEM_POS+1, 0);
941 if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
942 error("inst specifies different size than registers used");
943 op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
944 op[1] = rlist_bitmask;
950 size = find_size2(inst_size, $2, $4);
952 op[1] = reg($2) * 16 + reg($4);
956 size = find_size2(inst_size, $2, $4);
959 op[1] = reg($2) * 16 + reg($4);
962 op[1] = reg($2) * 16 + reg($4);
965 | MUL REG ',' '#' expr {
967 size = find_size1(inst_size, $2);
970 op[2] = msb(imm_data16($5));
971 op[3] = lsb(imm_data16($5));
972 RELOC_ABS_FFFF(MEM_POS+2, 0);
974 | MULU REG ',' '#' expr {
975 size = find_size2(inst_size, $2, $4);
979 op[1] = reg($2) * 16;
980 op[2] = imm_data8($5);
981 RELOC_ABS_FF(MEM_POS+2, 0);
985 op[1] = reg($2) * 16;
986 op[2] = msb(imm_data16($5));
987 op[3] = lsb(imm_data16($5));
988 RELOC_ABS_FFFF(MEM_POS+2, 0);
993 size = find_size2(inst_size, $2, $4);
996 error("Signed DIV can't be 8 bit size"); break;
999 op[1] = reg($2) * 16 + reg($4);
1003 op[1] = (reg($2) / 2) * 32 + reg($4);
1007 | DIVU REG ',' REG {
1009 size = find_size2(inst_size, $2, $4);
1013 op[1] = reg($2) * 16 + reg($4);
1017 op[1] = reg($2) * 16 + reg($4);
1021 op[1] = (reg($2) / 2) * 32 + reg($4);
1025 | DIV REG ',' '#' expr {
1026 size = find_size1(inst_size, $2);
1029 error("Singed DIV can't be 8 bit size"); break;
1033 op[1] = reg($2) * 16 + 11;
1034 op[2] = imm_data8($5);
1035 RELOC_ABS_FF(MEM_POS+2, 0);
1040 op[1] = (reg($2) / 2) * 32 + 9;
1041 op[2] = msb(imm_data16($5));
1042 op[3] = lsb(imm_data16($5));
1043 RELOC_ABS_FFFF(MEM_POS+2, 0);
1047 | DIVU REG ',' '#' expr {
1048 size = find_size1(inst_size, $2);
1053 op[1] = reg($2) * 16 + 1;
1054 op[2] = imm_data8($5);
1055 RELOC_ABS_FF(MEM_POS+2, 0);
1060 op[1] = reg($2) * 16 + 3;
1061 op[2] = imm_data8($5);
1062 RELOC_ABS_FF(MEM_POS+2, 0);
1067 op[1] = (reg($2) / 2) * 32 + 1;
1068 op[2] = msb(imm_data16($5));
1069 op[3] = lsb(imm_data16($5));
1070 RELOC_ABS_FFFF(MEM_POS+2, 0);
1074 | CALL '[' REG ']' {
1082 op[1] = ($2 >> 8) & 255;
1084 op[3] = ($2 >> 16) & 255;
1089 op[1] = ($2 >> 8) & 255;
1091 op[3] = ($2 >> 16) & 255;
1096 op[1] = 0x70 + reg_indirect($3);
1098 | JMP '[' A '+' DPTR ']' {
1103 | JMP '[' '[' REG '+' ']' ']' {
1106 op[1] = 0x60 + reg_indirect($4);
1112 op[1] = msb(rel16(MEM_POS + $$, $2));
1113 op[2] = lsb(rel16(MEM_POS + $$, $2));
1114 RELOC_FFFF(MEM_POS+1,MEM_POS+$$,0);
1120 op[1] = msb(rel16(MEM_POS + $$, $2));
1121 op[2] = lsb(rel16(MEM_POS + $$, $2));
1122 RELOC_FFFF(MEM_POS+1, MEM_POS+$$, 0);
1124 | branch_inst jmpaddr {
1126 op[0] = branch_opcode;
1127 op[1] = rel8(MEM_POS + $$, $2);
1128 RELOC_FF(MEM_POS+1,MEM_POS + $$, 0);
1130 | CJNE REG ',' expr ',' jmpaddr {
1132 size = find_size1(inst_size, $2);
1133 op[0] = 0xE2 + size * 8;
1134 op[1] = reg($2) * 16 + msb(direct_addr($4));
1135 op[2] = lsb(direct_addr($4));
1136 op[3] = rel8(MEM_POS + $$, $6);
1137 RELOC_DIR_07FF(MEM_POS+1, 0);
1138 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1140 | CJNE REG ',' '#' expr ',' jmpaddr {
1141 size = find_size1(inst_size, $2);
1142 if (size == SIZE8) {
1145 op[1] = reg($2) * 16;
1146 op[2] = rel8(MEM_POS + $$, $7);
1147 op[3] = imm_data8($5);
1148 RELOC_ABS_FF(MEM_POS+3, 0);
1152 op[1] = reg($2) * 16;
1153 op[2] = rel8(MEM_POS + $$, $7);
1154 op[3] = msb(imm_data16($5));
1155 op[4] = lsb(imm_data16($5));
1156 RELOC_ABS_FFFF(MEM_POS+3, 0);
1159 | CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
1160 size = find_size0(inst_size);
1161 if (size == SIZE8) {
1164 op[1] = reg_indirect($3) * 16 + 8;
1165 op[2] = rel8(MEM_POS + $$, $9);
1166 op[3] = imm_data8($7);
1167 RELOC_ABS_FF(MEM_POS+3, 0);
1171 op[1] = reg_indirect($3) * 16 + 8;
1172 op[2] = rel8(MEM_POS + $$, $9);
1173 op[3] = msb(imm_data16($7));
1174 op[4] = lsb(imm_data16($7));
1175 RELOC_ABS_FFFF(MEM_POS+3, 0);
1178 | DJNZ REG ',' jmpaddr {
1180 size = find_size1(inst_size, $2);
1181 op[0] = 0x87 + size * 8;
1182 op[1] = reg($2) * 16 + 8;
1183 op[2] = rel8(MEM_POS + $$, $4);
1184 RELOC_FF(MEM_POS+2, MEM_POS+$$, 0);
1188 | DJNZ WORD ',' jmpaddr {
1190 size = find_size0(inst_size);
1191 op[0] = 0xE2 + size * 8;
1192 op[1] = msb(direct_addr($2)) + 8;
1193 op[2] = lsb(direct_addr($2));
1194 op[3] = rel8(MEM_POS + $$, $4);
1195 RELOC_DIR_07FF(MEM_POS+1, 0);
1196 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1)
1199 | JB bit ',' jmpaddr {
1202 op[1] = 0x80 + msb(bit_addr($2));
1203 op[2] = lsb(bit_addr($2));
1204 op[3] = rel8(MEM_POS + $$, $4);
1205 RELOC_BIT_03FF(MEM_POS+1, 0);
1206 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1209 | JBC bit ',' jmpaddr {
1212 op[1] = 0xC0 + msb(bit_addr($2));
1213 op[2] = lsb(bit_addr($2));
1214 op[3] = rel8(MEM_POS + $$, $4);
1215 RELOC_BIT_03FF(MEM_POS+1, 0);
1216 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1219 | JNB bit ',' jmpaddr {
1222 op[1] = 0xA0 + msb(bit_addr($2));
1223 op[2] = lsb(bit_addr($2));
1224 op[3] = rel8(MEM_POS + $$, $4);
1225 RELOC_BIT_03FF(MEM_POS+1, 0);
1226 RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
1231 ADD {arith_opcode = 0;}
1232 | ADDC {arith_opcode = 1;}
1233 | AND {arith_opcode = 5;}
1234 | CMP {arith_opcode = 4;}
1235 | MOV {arith_opcode = 8;}
1236 | OR {arith_opcode = 6;}
1237 | SUB {arith_opcode = 2;}
1238 | SUBB {arith_opcode = 3;}
1239 | XOR {arith_opcode = 7;}
1242 ADDS {short_opcode = 0xA0;}
1243 | MOVS {short_opcode = 0xB0;}
1246 ASL {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
1247 | ASR {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
1248 | LSR {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
1249 | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
1252 RL {rotate_opcode = 0xD3;}
1253 | RLC {rotate_opcode = 0xD7;}
1254 | RR {rotate_opcode = 0xD0;}
1255 | RRC {rotate_opcode = 0xD7;}
1258 POP {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
1259 | POPU {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
1260 | PUSH {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
1261 | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
1264 BKPT {num_op = 1; opcode0 = 255; opcode1 = 0;}
1265 | NOP {num_op = 1; opcode0 = 0; opcode1 = 0;}
1266 | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
1267 | RET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
1268 | RETI {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
1271 BCC {branch_opcode = 0xF0;}
1272 | BCS {branch_opcode = 0xF1;}
1273 | BEQ {branch_opcode = 0xF3;}
1274 | BG {branch_opcode = 0xF8;}
1275 | BGE {branch_opcode = 0xFA;}
1276 | BGT {branch_opcode = 0xFC;}
1277 | BL {branch_opcode = 0xF9;}
1278 | BLE {branch_opcode = 0xFD;}
1279 | BLT {branch_opcode = 0xFB;}
1280 | BMI {branch_opcode = 0xF7;}
1281 | BNE {branch_opcode = 0xF2;}
1282 | BNV {branch_opcode = 0xF4;}
1283 | BOV {branch_opcode = 0xF5;}
1284 | BPL {branch_opcode = 0xF6;}
1285 | BR {branch_opcode = 0xFE;}
1286 | JZ {branch_opcode = 0xEC;}
1287 | JNZ {branch_opcode = 0xEE;}
1294 int reg(int reg_spec)
1296 return reg_spec & 15;
1299 int reg_indirect(int reg_spec)
1301 if (reg_spec & BYTE_REG)
1302 error("Indirect addressing may not use byte registers");
1303 if ((reg_spec & 15) > 7)
1304 error("Only R0 through R7 may be used for indirect addr");
1305 return reg_spec & 7;
1308 int rel16(int pos, int dest)
1312 if (!p3) return 0; /* don't bother unless writing code */
1313 if (dest & (BRANCH_SPACING - 1))
1314 error("Attempt to jump to unaligned location");
1315 pos &= ~(BRANCH_SPACING - 1);
1316 rel = (dest - pos) / BRANCH_SPACING;
1317 if (rel < -32768 || rel > 32767)
1318 error("Attempt to jump out of 16 bit relative range");
1319 if (rel < 0) rel += 65536;
1323 int rel8(int pos, int dest)
1327 if (!p3) return 0; /* don't bother unless writing code */
1328 if (dest & (BRANCH_SPACING - 1))
1329 error("Attempt to jump to unaligned location");
1330 pos &= ~(BRANCH_SPACING - 1);
1331 rel = (dest - pos) / BRANCH_SPACING;
1332 if (rel < -128 || rel > 127)
1333 error("Attempt to jump out of 16 bit relative range");
1334 if (rel < 0) rel += 256;
1340 return (value >> 8) & 255;
1348 int direct_addr(int value)
1352 if (value < 0 || value > 2047) {
1353 sprintf(buf, "illegal value (%d) for direct address", value);
1359 int imm_data4_signed(int value)
1361 if (value < -8 || value > 7)
1362 error("illegal 4 bit (signed) value");
1363 if (value >= 0) return value;
1364 else return (16 + value);
1367 int imm_data4_unsigned(int value)
1369 if (value < 0 || value > 15)
1370 error("illegal 4 bit (unsigned) value");
1374 int imm_data5_unsigned(int value)
1376 if (value < 0 || value > 31)
1377 error("illegal 5 bit (unsigned) value");
1381 int imm_data8(int value)
1383 if (value < -128 || value > 255)
1384 error("illegal 8 bit value");
1385 if (value >= 0) return value;
1386 else return (256 + value);
1389 int imm_data16(int value)
1391 if (value < -32728 || value > 65535)
1392 error("illegal 16 bit value");
1393 if (value >= 0) return value;
1394 else return (65536 + value);
1397 int bit_addr(int value)
1399 if (value < 0 || value > 1023) {
1400 fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
1402 error("illegal bit address");
1408 int find_size_reg(int op1spec)
1410 int op1size=UNKNOWN;
1412 if (op1spec & BYTE_REG) op1size = SIZE8;
1413 if (op1spec & WORD_REG) op1size = SIZE16;
1414 if (op1size == UNKNOWN)
1415 error("Register without implied size");
1419 int find_size0(int isize)
1421 if (isize == UNKNOWN)
1422 error("Can't determine data size from instruction");
1426 int find_size1(int isize, 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");
1435 if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
1436 if (isize == UNKNOWN) return op1size;
1438 if (isize != op1size)
1439 error("data size of register and inst don't agree");
1444 int find_size2(int isize, int op1spec, int op2spec)
1446 int op1size=UNKNOWN, op2size=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");
1452 if (op2spec & BYTE_REG) op2size = SIZE8;
1453 if (op2spec & WORD_REG) op2size = SIZE16;
1454 if (op1size == UNKNOWN)
1455 error("Register without implied size");
1457 if (op1size != op2size)
1458 error("data sizes of two registers don't agree");
1459 if (isize == UNKNOWN) return op1size;
1461 if (isize != op1size)
1462 error("data size of registers and inst don't agree");
1467 int yyerror(char *s)
1469 if (yytext[0] >= 32) {
1470 fprintf(stderr, "%s near '%s', line %d\n",
1473 fprintf(stderr, "%s, line %d\n", s, lineno - 1);