2 /* xa_rasm.y - This file is part of Paul's XA51 Assembler
4 Copyright 1997,2002 Paul Stoffregen (paul at pjrc dot com)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 /* Author contact: paul@pjrc.com */
21 /* parser for the 51-XA assembler, Paul Stoffregen, July 1997 */
31 int arith_opcode
, short_opcode
, num_op
, opcode0
, opcode1
;
32 int shift_imm_opcode
, shift_reg_opcode
, rotate_opcode
;
33 int stack_addr_opcode
, stack_reg_opcode
, branch_opcode
;
34 int rlist_reg_bank
, rlist_bitmask
, rlist_size
;
35 int db_count
, dw_count
, i
;
36 char symbol_name
[MAX_SYMBOL
], base_symbol_name
[MAX_SYMBOL
]={'\0'};
37 char operand
[2][MAX_SYMBOL
]={{'\0'},{'\0'}};
39 extern
char lex_sym_name
[];
42 extern
void yyrestart
(FILE *new_file
);
43 extern
char * disasm
(int byte
, int memory_location
);
47 void RELOC_FF
(unsigned where
, unsigned pc
, short rl
) {
48 // pc = PC of the next instruction
50 if
((sym
=findSymbol
(operand
[0]))) {
51 if
(sym
->mode
=='X' || sym
->area
!=current_area
) {
52 sprintf
(rel_line
[rl
], "R %04x REL_FF %s %04x",
53 where
, sym
->name
, pc
);
58 void RELOC_FFFF
(unsigned where
, unsigned pc
, short rl
) {
60 if
((sym
=findSymbol
(operand
[0]))) {
61 if
(sym
->mode
=='X' || sym
->area
!=current_area
) {
62 sprintf
(rel_line
[rl
], "R %04x REL_FFFF %s %04x",
63 where
, sym
->name
, pc
);
68 void RELOC_ABS_0F
(unsigned where
, int seq
) {
70 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
71 sprintf
(rel_line
[seq
], "R %04x ABS_0F %s 0", where
, sym
->name
);
75 void RELOC_BIT_03FF
(unsigned where
, int seq
) {
77 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
78 sprintf
(rel_line
[seq
], "R %04x BIT_03FF %s 0", where
, sym
->name
);
82 void RELOC_DIR_07FF
(unsigned where
, int seq
) {
84 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
85 sprintf
(rel_line
[seq
], "R %04x DIR_07FF %s 0", where
, sym
->name
);
89 void RELOC_DIR_70FF
(unsigned where
, int seq
) {
91 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
92 sprintf
(rel_line
[seq
], "R %04x DIR_70FF %s 0", where
, sym
->name
);
96 void RELOC_ABS_FF
(unsigned where
, int seq
) {
98 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
99 sprintf
(rel_line
[seq
], "R %04x DIR_FF %s 0", where
, sym
->name
);
103 void RELOC_ABS_FFFF
(unsigned where
, int seq
) {
105 if
((sym
=findSymbol
(operand
[seq
]))) {
108 // sfr or sbit, already in instruction
110 // equat, already in instruction
113 // external reference
114 sprintf
(rel_line
[seq
], "R %04x ABS_FFFF %s %04x", where
, sym
->name
,
118 // absolute in current segment
119 sprintf
(rel_line
[seq
], "R %04x ABS_PC PC %04x", where
, sym
->value
);
122 fprintf
(stderr
, "unknown ABS_FFFF\n");
128 void RELOC_DIR_0700FF
(unsigned where
, int seq
) {
130 if
((sym
=findSymbol
(operand
[seq
])) && sym
->mode
!='A') {
131 sprintf
(rel_line
[seq
], "R %04x ABS_0700FF %s 0", where
, sym
->name
);
137 %token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
138 %token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
139 %token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
140 %token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
141 %token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
142 %token SETB SEXT SUB SUBB TRAP XCH XOR
143 %token REG DPTR PC A C USP
144 %token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
145 %token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
147 %token AREA AREA_NAME AREA_DESC DS
160 line: linesymbol
':' linenosym
{
162 build_sym_list
(symbol_name
);
163 if
(current_area
== AREA_BSEG
) {
164 mk_bit
(symbol_name
, current_area
);
167 if
(p1 || p2
) assign_value
(symbol_name
, MEM_POS
, 'R');
171 if
(!is_abs
(symbol_name
)) {
176 linenosym: directive EOL
{
185 if
(p3
) out
(NULL
, 0);
188 |
error EOL
/* try to recover from any parse error */
191 directive: '.' ORG expr
{
199 |
'.' EQU symbol
',' expr
{
200 if
(p1
) build_sym_list
(symbol_name
);
201 if
(p1 || p2
) assign_value
(symbol_name
, $5, '?');
205 if
(p1
) build_sym_list
(symbol_name
);
206 if
(p1 || p2
) assign_value
(symbol_name
, $3, '=');
209 if
(p1
) build_sym_list
(symbol_name
);
210 if
(p1 || p2
) assign_value
(symbol_name
, $3, 'A');
211 if
(p1 || p2
) mk_sfr
(symbol_name
);
214 |
'.' BITDEF bitsymbol
',' bit
{
216 build_sym_list
(symbol_name
);
217 mk_bit
(symbol_name
, 0);
219 if
(p1 || p2
) assign_value
(symbol_name
, $5, '?');
222 | bitsymbol BITDEF bit
{
224 build_sym_list
(symbol_name
);
225 mk_bit
(symbol_name
, 0);
227 if
(p1 || p2
) assign_value
(symbol_name
, $3, '?');
230 | bitsymbol BITDEF expr
{
232 build_sym_list
(symbol_name
);
233 mk_bit
(symbol_name
, 0);
235 if
(p1 || p2
) assign_value
(symbol_name
, $3, 'A');
238 |
'.' REGDEF regsymbol
',' REG
{
240 build_sym_list
(symbol_name
);
243 if
(p1 || p2
) assign_value
(symbol_name
, $5, '?');
246 | regsymbol REGDEF REG
{
248 build_sym_list
(symbol_name
);
251 if
(p1 || p2
) assign_value
(symbol_name
, $3, '?');
255 |
'.' db_directive bytes
{
258 |
'.' dw_directive words
{
261 |
'.' AREA AREA_NAME AREA_DESC
{
262 if
($3 < 0 ||
$3 > NUM_AREAS
) {
263 error("Illegal Area Directive");
265 symbol_name
[0] = '\0';
270 /* ignore module definition */
274 mk_global
(lex_sym_name
);
275 /* ignore global symbol declaration */
279 /* ignore bit symbol declaration */
283 /* todo: if CSEG, emit some filler bytes */
287 db_directive: DB
{db_count
= 0;}
290 linesymbol: normal_or_bit_symbol
{
291 strcpy
(symbol_name
, lex_sym_name
);
292 if
(!strchr
(lex_sym_name
, ':')) {
293 /* non-local label, remember base name */
294 strcpy
(base_symbol_name
, lex_sym_name
);
296 if
(is_target
(symbol_name
)) pad_with_nop
();
299 normal_or_bit_symbol: WORD
{$$
= $1;}
303 | bytes
',' byte_element
306 op
[db_count
] = $1 & 255;
307 if
(++db_count
>= MAX_DB
) {
308 error("too many bytes, use two DB");
313 for
(i
=1; i
< strlen
(yytext
)-1; i
++) {
314 op
[db_count
++] = yytext
[i
];
315 if
(db_count
>= MAX_DB
) {
316 error("too many bytes, use two DB");
322 dw_directive: DW
{dw_count
= 0;}
324 words: words
',' word_element
328 op
[dw_count
] = $1 & 255;
329 op
[dw_count
+1] = ($1 >> 8) & 255;
331 if
(dw_count
>= MAX_DB
) {
332 error("too many bytes, use two DW");
340 strcpy
(symbol_name
, lex_sym_name
);
343 bitsymbol: WORD
{ strcpy
(symbol_name
, lex_sym_name
); }
344 | BIT
{ strcpy
(symbol_name
, lex_sym_name
); }
347 regsymbol: WORD
{ strcpy
(symbol_name
, lex_sym_name
); }
348 | REG
{ strcpy
(symbol_name
, lex_sym_name
); }
351 if
($3 < 0 ||
$3 > 7) {
352 /* only 8 bits in a byte */
353 error("Only eight bits in a byte");
355 $$
= 100000; /* should really check $1 is valid */
356 if
($1 >= 0x20 && $1 <= 0x3F) {
359 if
($1 >= 0x400 && $1 <= 0x43F) {
360 $$
= ($1 - 0x400) * 8 + $3 + 0x200;
365 if
(find_size_reg
($1) == SIZE8
) {
366 if
($3 < 0 ||
$3 > 7)
367 error("byte reg has only 8 bits");
368 $$
= reg
($1) * 8 + $3;
370 if
(find_size_reg
($1) == SIZE16
) {
371 if
($3 < 0 ||
$3 > 15)
372 error("word reg has only 16 bits");
373 $$
= reg
($1) * 16 + $3;
380 if
(p1
) build_target_list
(lex_sym_name
);
383 if
($1 & 1) error("Jump target must be aligned");
388 expr: value
{$$
= $1;}
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
'^' expr
{$$
= $1 ^
$3;}
396 | expr RSHIFT expr
{$$
= $1 >> $3;}
397 | expr LSHIFT expr
{$$
= $1 << $3;}
398 |
'-' expr %prec UNARY
{$$
= $2 * -1;}
399 |
'+' expr %prec UNARY
{$$
= $2;}
400 |
'(' expr
')' {$$
= $2;}
401 | LOW expr %prec UNARY
{$$
= $2 & 255;}
402 | HIGH expr %prec UNARY
{$$
= ($2 >> 8) & 255;}
405 value: NUMBER
{$$
= $1;}
410 rlist_bitmask
= 1<<(reg
($1) %
8);
411 rlist_reg_bank
= (reg
($1) / 8) ?
1 : 0;
412 rlist_size
= find_size_reg
($1);
415 rlist_bitmask |
= 1<<(reg
($1) %
8);
416 if
(rlist_reg_bank
!= ((reg
($1) / 8) ?
1 : 0))
417 error("register list may not mix 0-7/8-15 regs");
418 if
(rlist_size
!= find_size_reg
($1))
419 error("register list may not mix 8/16 bit registers");
428 arith_inst REG
',' REG
{
430 size
= find_size2
(inst_size
, $2, $4);
431 op
[0] = arith_opcode
* 16 + size
* 8 + 1;
432 op
[1] = reg
($2) * 16 + reg
($4);
434 | arith_inst REG
',' '[' REG
']' {
436 size
= find_size1
(inst_size
, $2);
437 op
[0] = arith_opcode
* 16 + size
* 8 + 2;
438 op
[1] = reg
($2) * 16 + reg_indirect
($5);
440 | arith_inst
'[' REG
']' ',' REG
{
442 size
= find_size1
(inst_size
, $6);
443 op
[0] = arith_opcode
* 16 + size
* 8 + 2;
444 op
[1] = reg
($6) * 16 + 8 + reg_indirect
($3);
446 | arith_inst REG
',' '[' REG
'+' expr
']' {
447 size
= find_size1
(inst_size
, $2);
448 if
($7 >= -128 && $7 <= 127) {
450 op
[0] = arith_opcode
* 16 + size
* 8 + 4;
451 op
[1] = reg
($2) * 16 + reg_indirect
($5);
452 op
[2] = ($7 >= 0) ?
$7 : 256 + $7;
453 RELOC_ABS_FF
(MEM_POS
+2,0);
456 op
[0] = arith_opcode
* 16 + size
* 8 + 5;
457 op
[1] = reg
($2) * 16 + reg_indirect
($5);
458 op
[2] = ($7 >= 0) ? msb
($7) : msb
(65536 + $7);
459 op
[3] = ($7 >= 0) ? lsb
($7) : lsb
(65536 + $7);
460 RELOC_ABS_FFFF
(MEM_POS
+2,0);
463 | arith_inst
'[' REG
'+' expr
']' ',' REG
{
464 size
= find_size1
(inst_size
, $8);
465 if
($5 >= -128 && $5 <= 127) {
467 op
[0] = arith_opcode
* 16 + size
* 8 + 4;
468 op
[1] = reg
($8) * 16 + 8 + reg_indirect
($3);
469 op
[2] = ($5 >= 0) ?
$5 : 256 + $5;
470 RELOC_ABS_FF
(MEM_POS
+2,0);
473 op
[0] = arith_opcode
* 16 + size
* 8 + 5;
474 op
[1] = reg
($8) * 16 + 8 + reg_indirect
($3);
475 op
[2] = ($5 >= 0) ? msb
($5) : msb
(65536 + $5);
476 op
[3] = ($5 >= 0) ? lsb
($5) : lsb
(65536 + $5);
477 RELOC_ABS_FFFF
(MEM_POS
+2,0);
480 | arith_inst REG
',' '[' REG
'+' ']' {
482 size
= find_size1
(inst_size
, $2);
483 op
[0] = arith_opcode
* 16 + size
* 8 + 3;
484 op
[1] = reg
($2) * 16 + reg_indirect
($5);
486 | arith_inst
'[' REG
'+' ']' ',' REG
{
488 size
= find_size1
(inst_size
, $7);
489 op
[0] = arith_opcode
* 16 + size
* 8 + 3;
490 op
[1] = reg
($7) * 16 + 8 + reg_indirect
($3);
492 | arith_inst WORD
',' REG
{
494 size
= find_size1
(inst_size
, $4);
495 op
[0] = arith_opcode
* 16 + size
* 8 + 6;
496 op
[1] = reg
($4) * 16 + 8 + msb
(direct_addr
($2));
497 op
[2] = lsb
(direct_addr
($2));
498 RELOC_DIR_07FF
(MEM_POS
+1, 0);
500 | arith_inst REG
',' WORD
{
502 size
= find_size1
(inst_size
, $2);
503 op
[0] = arith_opcode
* 16 + size
* 8 + 6;
504 op
[1] = reg
($2) * 16 + msb
(direct_addr
($4));
505 op
[2] = lsb
(direct_addr
($4));
506 RELOC_DIR_07FF
(MEM_POS
+1, 0);
508 | arith_inst REG
',' '#' expr
{
509 size
= find_size1
(inst_size
, $2);
513 op
[1] = reg
($2) * 16 + arith_opcode
;
514 op
[2] = imm_data8
($5);
515 RELOC_ABS_FF
(MEM_POS
+2, 0);
519 op
[1] = reg
($2) * 16 + arith_opcode
;
520 op
[2] = msb
(imm_data16
($5));
521 op
[3] = lsb
(imm_data16
($5));
522 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
525 | arith_inst
'[' REG
']' ',' '#' expr
{
526 size
= find_size0
(inst_size
);
530 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
531 op
[2] = imm_data8
($7);
532 RELOC_ABS_FF
(MEM_POS
+2, 0);
536 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
537 op
[2] = msb
(imm_data16
($7));
538 op
[3] = lsb
(imm_data16
($7));
539 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
542 | arith_inst
'[' REG
'+' ']' ',' '#' expr
{
543 size
= find_size0
(inst_size
);
547 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
548 op
[2] = imm_data8
($8);
549 RELOC_ABS_FF
(MEM_POS
+2, 0);
553 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
554 op
[2] = msb
(imm_data16
($8));
555 op
[3] = lsb
(imm_data16
($8));
556 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
559 | arith_inst
'[' REG
'+' expr
']' ',' '#' expr
{
560 size
= find_size0
(inst_size
);
561 if
($5 >= -128 && $5 <= 127) {
565 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
566 op
[2] = ($5 >= 0) ?
$5 : 256 + $5;
567 op
[3] = imm_data8
($9);
568 RELOC_ABS_FF
(MEM_POS
+2, 0);
569 RELOC_ABS_FF
(MEM_POS
+3, 1);
573 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
574 op
[2] = ($5 >= 0) ?
$5 : 256 + $5;
575 op
[3] = msb
(imm_data16
($9));
576 op
[4] = lsb
(imm_data16
($9));
577 RELOC_ABS_FF
(MEM_POS
+2, 0);
578 RELOC_ABS_FFFF
(MEM_POS
+3, 1);
584 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
585 op
[2] = ($5 >= 0) ? msb
($5) : msb
(65536 + $5);
586 op
[3] = ($5 >= 0) ? lsb
($5) : lsb
(65536 + $5);
587 op
[4] = imm_data8
($9);
588 RELOC_ABS_FFFF
(MEM_POS
+2,0);
589 RELOC_ABS_FF
(MEM_POS
+4,1);
593 op
[1] = reg_indirect
($3) * 16 + arith_opcode
;
594 op
[2] = ($5 >= 0) ? msb
($5) : msb
(65536 + $5);
595 op
[3] = ($5 >= 0) ? lsb
($5) : lsb
(65536 + $5);
596 op
[4] = msb
(imm_data16
($9));
597 op
[5] = lsb
(imm_data16
($9));
598 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
599 RELOC_ABS_FFFF
(MEM_POS
+4, 1);
603 | arith_inst WORD
',' '#' expr
{
604 size
= find_size0
(inst_size
);
608 op
[1] = msb
(direct_addr
($2)) * 16 + arith_opcode
;
609 op
[2] = lsb
(direct_addr
($2));
610 op
[3] = imm_data8
($5);
611 RELOC_DIR_70FF
(MEM_POS
+1,0);
612 RELOC_ABS_FF
(MEM_POS
+3,1);
616 op
[1] = msb
(direct_addr
($2)) * 16 + arith_opcode
;
617 op
[2] = lsb
(direct_addr
($2));
618 op
[3] = msb
(imm_data16
($5));
619 op
[4] = lsb
(imm_data16
($5));
620 RELOC_DIR_70FF
(MEM_POS
+1,0);
621 RELOC_ABS_FFFF
(MEM_POS
+3,1);
625 /* the next 8 instructions are MOV, but because MOV was used in the */
626 /* arith_inst group, it will cause a shift/reduce conflict if used */
627 /* directly below... so we're forced to use arith_inst and then */
628 /* add a bit of code to make sure it was MOV and not the other ones */
630 | arith_inst
'[' REG
'+' ']' ',' '[' REG
'+' ']' {
631 /* this addr mode is only valid for MOV */
632 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (1)");
633 size
= find_size0
(inst_size
);
635 op
[0] = 0x90 + size
* 8;
636 op
[1] = reg_indirect
($3) * 16 + reg_indirect
($8);
638 | arith_inst WORD
',' '[' REG
']' {
639 /* this addr mode is only valid for MOV */
640 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (2)");
641 size
= find_size0
(inst_size
);
643 op
[0] = 0xA0 + size
* 8;
644 op
[1] = 128 + reg_indirect
($5) * 16 + msb
(direct_addr
($2));
645 op
[2] = lsb
(direct_addr
($2));
646 RELOC_DIR_07FF
(MEM_POS
+1, 0);
648 | arith_inst
'[' REG
']' ',' WORD
{
649 /* this addr mode is only valid for MOV */
650 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (3)");
651 size
= find_size0
(inst_size
);
653 op
[0] = 0xA0 + size
* 8;
654 op
[1] = reg_indirect
($3) * 16 + msb
(direct_addr
($6));
655 op
[2] = lsb
(direct_addr
($6));
656 RELOC_DIR_07FF
(MEM_POS
+1, 0);
658 | arith_inst WORD
',' WORD
{
659 /* this addr mode is only valid for MOV */
660 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (4)");
661 size
= find_size0
(inst_size
);
663 op
[0] = 0x97 + size
* 8;
664 op
[1] = msb
(direct_addr
($2)) * 16 + msb
(direct_addr
($4));
665 op
[2] = lsb
(direct_addr
($2));
666 op
[3] = lsb
(direct_addr
($4));
667 RELOC_DIR_70FF
(MEM_POS
+1, 0);
668 RELOC_DIR_0700FF
(MEM_POS
+1, 1);
670 | arith_inst REG
',' USP
{
671 /* this addr mode is only valid for MOV */
672 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (5)");
675 op
[1] = reg
($2) * 16 + 15;
677 | arith_inst USP
',' REG
{
678 /* this addr mode is only valid for MOV */
679 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (6)");
682 op
[1] = reg
($4) * 16 + 15;
684 | arith_inst C
',' bit
{
685 /* this addr mode is only valid for MOV */
686 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (7)");
689 op
[1] = 0x20 + msb
(bit_addr
($4));
690 op
[2] = lsb
(bit_addr
($4));
691 RELOC_BIT_03FF
(MEM_POS
+1, 0);
693 | arith_inst bit
',' C
{
694 /* this addr mode is only valid for MOV */
695 if
(arith_opcode
!= 8) error("Addr mode only valid for MOV (8)");
698 op
[1] = 0x30 + msb
(bit_addr
($2));
699 op
[2] = lsb
(bit_addr
($2));
700 RELOC_BIT_03FF
(MEM_POS
+1, 0);
703 | MOVC REG
',' '[' REG
'+' ']' {
704 size
= find_size1
(inst_size
, $2);
706 op
[0] = 0x80 + size
* 8;
707 op
[1] = reg
($2) * 16 + reg_indirect
($5);
709 | MOVC A
',' '[' A
'+' DPTR
']' {
714 | MOVC A
',' '[' A
'+' PC
']' {
719 | MOVX REG
',' '[' REG
']' {
721 size
= find_size1
(inst_size
, $2);
722 op
[0] = 0xA7 + size
* 8;
723 op
[1] = reg
($2) * 16 + reg_indirect
($5);
725 | MOVX
'[' REG
']' ',' REG
{
727 size
= find_size1
(inst_size
, $6);
728 op
[0] = 0xA7 + size
* 8;
729 op
[1] = reg
($6) * 16 + 8 + reg_indirect
($3);
733 size
= find_size2
(inst_size
, $2, $4);
734 op
[0] = 0x60 + size
* 8;
735 op
[1] = reg
($2) * 16 + reg
($4);
737 | XCH REG
',' '[' REG
']' {
739 size
= find_size1
(inst_size
, $2);
740 op
[0] = 0x50 + size
* 8;
741 op
[1] = reg
($2) * 16 + reg_indirect
($5);
745 size
= find_size1
(inst_size
, $2);
746 op
[0] = 0xA0 + size
* 8;
747 op
[1] = reg
($2) * 16 + msb
(direct_addr
($4));
748 op
[2] = lsb
(direct_addr
($4));
749 RELOC_DIR_07FF
(MEM_POS
+1, 0);
751 | short_data_inst REG
',' '#' expr
{
753 size
= find_size1
(inst_size
, $2);
754 op
[0] = short_opcode
+ size
* 8 + 1;
755 op
[1] = reg
($2) * 16 + imm_data4_signed
($5);
756 RELOC_ABS_0F
(MEM_POS
+1, 0);
758 | short_data_inst
'[' REG
']' ',' '#' expr
{
760 size
= find_size0
(inst_size
);
761 op
[0] = short_opcode
+ size
* 8 + 2;
762 op
[1] = reg_indirect
($3) * 16 + imm_data4_signed
($7);
763 RELOC_ABS_0F
(MEM_POS
+1, 0);
765 | short_data_inst
'[' REG
'+' ']' ',' '#' expr
{
767 size
= find_size0
(inst_size
);
768 op
[0] = short_opcode
+ size
* 8 + 3;
769 op
[1] = reg_indirect
($3) * 16 + imm_data4_signed
($8);
770 RELOC_ABS_0F
(MEM_POS
+1, 0);
772 | short_data_inst
'[' REG
'+' expr
']' ',' '#' expr
{
773 size
= find_size0
(inst_size
);
774 if
($5 >= -128 && $5 <= 127) {
776 op
[0] = short_opcode
+ size
* 8 + 4;
777 op
[1] = reg_indirect
($3) * 16 + imm_data4_signed
($9);
778 op
[2] = op
[2] = ($5 >= 0) ?
$5 : 256 + $5;
779 RELOC_ABS_0F
(MEM_POS
+1, 1);
780 RELOC_ABS_FF
(MEM_POS
+2, 0);
783 op
[0] = short_opcode
+ size
* 8 + 5;
784 op
[1] = reg_indirect
($3) * 16 + imm_data4_signed
($9);
785 op
[2] = ($5 >= 0) ? msb
($5) : msb
(65536 + $5);
786 op
[3] = ($5 >= 0) ? lsb
($5) : lsb
(65536 + $5);
787 RELOC_ABS_0F
(MEM_POS
+1, 1);
788 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
791 | short_data_inst expr
',' '#' expr
{
793 size
= find_size0
(inst_size
);
794 op
[0] = short_opcode
+ size
* 8 + 6;
795 op
[1] = msb
(direct_addr
($2)) * 16 + imm_data4_signed
($5);
796 op
[2] = lsb
(direct_addr
($2));
797 RELOC_ABS_0F
(MEM_POS
+1, 0);
802 op
[1] = 0x40 + msb
(bit_addr
($4));
803 op
[2] = lsb
(bit_addr
($4));
804 RELOC_BIT_03FF
(MEM_POS
+1, 0);
806 | ANL C
',' '/' bit
{
809 op
[1] = 0x50 + msb
(bit_addr
($5));
810 op
[2] = lsb
(bit_addr
($5));
811 RELOC_BIT_03FF
(MEM_POS
+1, 0);
817 op
[1] = 0x60 + msb
(bit_addr
($4));
818 op
[2] = lsb
(bit_addr
($4));
819 RELOC_BIT_03FF
(MEM_POS
+1, 0);
821 | ORL C
',' '/' bit
{
824 op
[1] = 0x70 + msb
(bit_addr
($5));
825 op
[2] = lsb
(bit_addr
($5));
826 RELOC_BIT_03FF
(MEM_POS
+1, 0);
831 op
[1] = msb
(bit_addr
($2));
832 op
[2] = lsb
(bit_addr
($2));
833 RELOC_BIT_03FF
(MEM_POS
+1, 0);
838 op
[1] = 0x10 + msb
(bit_addr
($2));
839 op
[2] = lsb
(bit_addr
($2));
840 RELOC_BIT_03FF
(MEM_POS
+1, 0);
842 | logical_shift_inst REG
',' REG
{
843 size
= find_size1
(inst_size
, $2);
844 if
(find_size_reg
($4) != SIZE8
)
845 error("Second register in logical shift must be byte size");
847 op
[0] = shift_reg_opcode
;
849 case SIZE8
: op
[0] += 0; break
;
850 case SIZE16
: op
[0] += 8; break
;
851 case SIZE32
: op
[0] += 12; break
;
853 op
[1] = reg
($2) * 16 + reg
($4);
855 | logical_shift_inst REG
',' '#' NUMBER
{
856 size
= find_size1
(inst_size
, $2);
858 if
(shift_imm_opcode
== -1)
859 error("NORM may not use a constant");
860 op
[0] = shift_imm_opcode
;
862 case SIZE8
: op
[0] += 0; break
;
863 case SIZE16
: op
[0] += 8; break
;
864 case SIZE32
: op
[0] += 12; break
;
869 op
[1] = reg
($2) * 16 + imm_data4_unsigned
($5);
872 op
[1] = (reg
($2) / 2) * 32 + imm_data5_unsigned
($5);
885 op
[1] = 0x30 + imm_data4_unsigned
($3);
889 size
= find_size1
(inst_size
, $2);
890 op
[0] = 0x90 + size
* 8;
891 op
[1] = reg
($2) * 16 + 10;
896 op
[1] = reg
($2) * 16 + 8;
900 size
= find_size1
(inst_size
, $2);
901 op
[0] = 0x90 + size
* 8;
902 op
[1] = reg
($2) * 16 + 11;
906 size
= find_size1
(inst_size
, $2);
907 op
[0] = 0x90 + size
* 8;
908 op
[1] = reg
($2) * 16 + 9;
911 | rotate_inst REG
',' '#' NUMBER
{
913 size
= find_size1
(inst_size
, $2);
914 op
[0] = rotate_opcode
+ size
* 8;
915 op
[1] = reg
($2) * 16 + imm_data4_unsigned
($5);
919 | LEA REG
',' REG
'+' expr
{
920 if
($6 >= -128 && $6 <= 127) {
923 op
[1] = reg
($2) * 16 + reg_indirect
($4);
924 op
[2] = ($6 >= 0) ?
$6 : 256 + $6;
925 RELOC_ABS_FF
(MEM_POS
+2, 0);
928 op
[1] = reg
($2) * 16 + reg_indirect
($4);
929 op
[2] = ($6 >= 0) ? msb
($6) : msb
(65536 + $6);
930 op
[3] = ($6 >= 0) ? lsb
($6) : lsb
(65536 + $6);
931 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
936 size
= find_size0
(inst_size
);
937 op
[0] = msb
(stack_addr_opcode
) + size
* 8;
938 op
[1] = lsb
(stack_addr_opcode
) + msb
(direct_addr
($2));
939 op
[2] = lsb
(direct_addr
($2));
940 RELOC_DIR_07FF
(MEM_POS
+1, 0);
944 if
(inst_size
!= UNKNOWN
&& find_size0
(inst_size
) != rlist_size
)
945 error("inst specifies different size than registers used");
946 op
[0] = stack_reg_opcode
+ rlist_reg_bank
* 64 + rlist_size
* 8;
947 op
[1] = rlist_bitmask
;
953 size
= find_size2
(inst_size
, $2, $4);
955 op
[1] = reg
($2) * 16 + reg
($4);
959 size
= find_size2
(inst_size
, $2, $4);
962 op
[1] = reg
($2) * 16 + reg
($4);
965 op
[1] = reg
($2) * 16 + reg
($4);
968 | MUL REG
',' '#' expr
{
970 size
= find_size1
(inst_size
, $2);
973 op
[2] = msb
(imm_data16
($5));
974 op
[3] = lsb
(imm_data16
($5));
975 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
977 | MULU REG
',' '#' expr
{
978 size
= find_size2
(inst_size
, $2, $4);
982 op
[1] = reg
($2) * 16;
983 op
[2] = imm_data8
($5);
984 RELOC_ABS_FF
(MEM_POS
+2, 0);
988 op
[1] = reg
($2) * 16;
989 op
[2] = msb
(imm_data16
($5));
990 op
[3] = lsb
(imm_data16
($5));
991 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
996 size
= find_size2
(inst_size
, $2, $4);
999 error("Signed DIV can't be 8 bit size"); break
;
1002 op
[1] = reg
($2) * 16 + reg
($4);
1006 op
[1] = (reg
($2) / 2) * 32 + reg
($4);
1010 | DIVU REG
',' REG
{
1012 size
= find_size2
(inst_size
, $2, $4);
1016 op
[1] = reg
($2) * 16 + reg
($4);
1020 op
[1] = reg
($2) * 16 + reg
($4);
1024 op
[1] = (reg
($2) / 2) * 32 + reg
($4);
1028 | DIV REG
',' '#' expr
{
1029 size
= find_size1
(inst_size
, $2);
1032 error("Singed DIV can't be 8 bit size"); break
;
1036 op
[1] = reg
($2) * 16 + 11;
1037 op
[2] = imm_data8
($5);
1038 RELOC_ABS_FF
(MEM_POS
+2, 0);
1043 op
[1] = (reg
($2) / 2) * 32 + 9;
1044 op
[2] = msb
(imm_data16
($5));
1045 op
[3] = lsb
(imm_data16
($5));
1046 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
1050 | DIVU REG
',' '#' expr
{
1051 size
= find_size1
(inst_size
, $2);
1056 op
[1] = reg
($2) * 16 + 1;
1057 op
[2] = imm_data8
($5);
1058 RELOC_ABS_FF
(MEM_POS
+2, 0);
1063 op
[1] = reg
($2) * 16 + 3;
1064 op
[2] = imm_data8
($5);
1065 RELOC_ABS_FF
(MEM_POS
+2, 0);
1070 op
[1] = (reg
($2) / 2) * 32 + 1;
1071 op
[2] = msb
(imm_data16
($5));
1072 op
[3] = lsb
(imm_data16
($5));
1073 RELOC_ABS_FFFF
(MEM_POS
+2, 0);
1077 | CALL
'[' REG
']' {
1085 op
[1] = ($2 >> 8) & 255;
1087 op
[3] = ($2 >> 16) & 255;
1092 op
[1] = ($2 >> 8) & 255;
1094 op
[3] = ($2 >> 16) & 255;
1099 op
[1] = 0x70 + reg_indirect
($3);
1101 | JMP
'[' A
'+' DPTR
']' {
1106 | JMP
'[' '[' REG
'+' ']' ']' {
1109 op
[1] = 0x60 + reg_indirect
($4);
1115 op
[1] = msb
(rel16
(MEM_POS
+ $$
, $2));
1116 op
[2] = lsb
(rel16
(MEM_POS
+ $$
, $2));
1117 RELOC_FFFF
(MEM_POS
+1,MEM_POS
+$$
,0);
1123 op
[1] = msb
(rel16
(MEM_POS
+ $$
, $2));
1124 op
[2] = lsb
(rel16
(MEM_POS
+ $$
, $2));
1125 RELOC_FFFF
(MEM_POS
+1, MEM_POS
+$$
, 0);
1127 | branch_inst jmpaddr
{
1129 op
[0] = branch_opcode
;
1130 op
[1] = rel8
(MEM_POS
+ $$
, $2);
1131 RELOC_FF
(MEM_POS
+1,MEM_POS
+ $$
, 0);
1133 | CJNE REG
',' expr
',' jmpaddr
{
1135 size
= find_size1
(inst_size
, $2);
1136 op
[0] = 0xE2 + size
* 8;
1137 op
[1] = reg
($2) * 16 + msb
(direct_addr
($4));
1138 op
[2] = lsb
(direct_addr
($4));
1139 op
[3] = rel8
(MEM_POS
+ $$
, $6);
1140 RELOC_DIR_07FF
(MEM_POS
+1, 0);
1141 RELOC_FF
(MEM_POS
+3, MEM_POS
+ $$
, 1);
1143 | CJNE REG
',' '#' expr
',' jmpaddr
{
1144 size
= find_size1
(inst_size
, $2);
1145 if
(size
== SIZE8
) {
1148 op
[1] = reg
($2) * 16;
1149 op
[2] = rel8
(MEM_POS
+ $$
, $7);
1150 op
[3] = imm_data8
($5);
1151 RELOC_ABS_FF
(MEM_POS
+3, 0);
1155 op
[1] = reg
($2) * 16;
1156 op
[2] = rel8
(MEM_POS
+ $$
, $7);
1157 op
[3] = msb
(imm_data16
($5));
1158 op
[4] = lsb
(imm_data16
($5));
1159 RELOC_ABS_FFFF
(MEM_POS
+3, 0);
1162 | CJNE
'[' REG
']' ',' '#' expr
',' jmpaddr
{
1163 size
= find_size0
(inst_size
);
1164 if
(size
== SIZE8
) {
1167 op
[1] = reg_indirect
($3) * 16 + 8;
1168 op
[2] = rel8
(MEM_POS
+ $$
, $9);
1169 op
[3] = imm_data8
($7);
1170 RELOC_ABS_FF
(MEM_POS
+3, 0);
1174 op
[1] = reg_indirect
($3) * 16 + 8;
1175 op
[2] = rel8
(MEM_POS
+ $$
, $9);
1176 op
[3] = msb
(imm_data16
($7));
1177 op
[4] = lsb
(imm_data16
($7));
1178 RELOC_ABS_FFFF
(MEM_POS
+3, 0);
1181 | DJNZ REG
',' jmpaddr
{
1183 size
= find_size1
(inst_size
, $2);
1184 op
[0] = 0x87 + size
* 8;
1185 op
[1] = reg
($2) * 16 + 8;
1186 op
[2] = rel8
(MEM_POS
+ $$
, $4);
1187 RELOC_FF
(MEM_POS
+2, MEM_POS
+$$
, 0);
1191 | DJNZ WORD
',' jmpaddr
{
1193 size
= find_size0
(inst_size
);
1194 op
[0] = 0xE2 + size
* 8;
1195 op
[1] = msb
(direct_addr
($2)) + 8;
1196 op
[2] = lsb
(direct_addr
($2));
1197 op
[3] = rel8
(MEM_POS
+ $$
, $4);
1198 RELOC_DIR_07FF
(MEM_POS
+1, 0);
1199 RELOC_FF
(MEM_POS
+3, MEM_POS
+ $$
, 1)
1202 | JB bit
',' jmpaddr
{
1205 op
[1] = 0x80 + msb
(bit_addr
($2));
1206 op
[2] = lsb
(bit_addr
($2));
1207 op
[3] = rel8
(MEM_POS
+ $$
, $4);
1208 RELOC_BIT_03FF
(MEM_POS
+1, 0);
1209 RELOC_FF
(MEM_POS
+3, MEM_POS
+ $$
, 1);
1212 | JBC bit
',' jmpaddr
{
1215 op
[1] = 0xC0 + msb
(bit_addr
($2));
1216 op
[2] = lsb
(bit_addr
($2));
1217 op
[3] = rel8
(MEM_POS
+ $$
, $4);
1218 RELOC_BIT_03FF
(MEM_POS
+1, 0);
1219 RELOC_FF
(MEM_POS
+3, MEM_POS
+ $$
, 1);
1222 | JNB bit
',' jmpaddr
{
1225 op
[1] = 0xA0 + msb
(bit_addr
($2));
1226 op
[2] = lsb
(bit_addr
($2));
1227 op
[3] = rel8
(MEM_POS
+ $$
, $4);
1228 RELOC_BIT_03FF
(MEM_POS
+1, 0);
1229 RELOC_FF
(MEM_POS
+3, MEM_POS
+ $$
, 1);
1234 ADD
{arith_opcode
= 0;}
1235 | ADDC
{arith_opcode
= 1;}
1236 | AND
{arith_opcode
= 5;}
1237 | CMP
{arith_opcode
= 4;}
1238 | MOV
{arith_opcode
= 8;}
1239 | OR
{arith_opcode
= 6;}
1240 | SUB
{arith_opcode
= 2;}
1241 | SUBB
{arith_opcode
= 3;}
1242 | XOR
{arith_opcode
= 7;}
1245 ADDS
{short_opcode
= 0xA0;}
1246 | MOVS
{short_opcode
= 0xB0;}
1249 ASL
{shift_reg_opcode
= 0xC1; shift_imm_opcode
= 0xD1;}
1250 | ASR
{shift_reg_opcode
= 0xC2; shift_imm_opcode
= 0xD2;}
1251 | LSR
{shift_reg_opcode
= 0xC0; shift_imm_opcode
= 0xD0;}
1252 | NORM
{shift_reg_opcode
= 0xC3; shift_imm_opcode
= -1;}
1255 RL
{rotate_opcode
= 0xD3;}
1256 | RLC
{rotate_opcode
= 0xD7;}
1257 | RR
{rotate_opcode
= 0xD0;}
1258 | RRC
{rotate_opcode
= 0xD7;}
1261 POP
{stack_addr_opcode
= 0x8710; stack_reg_opcode
= 0x27;}
1262 | POPU
{stack_addr_opcode
= 0x8700; stack_reg_opcode
= 0x37;}
1263 | PUSH
{stack_addr_opcode
= 0x8730; stack_reg_opcode
= 0x07;}
1264 | PUSHU
{stack_addr_opcode
= 0x8720; stack_reg_opcode
= 0x17;}
1267 BKPT
{num_op
= 1; opcode0
= 255; opcode1
= 0;}
1268 | NOP
{num_op
= 1; opcode0
= 0; opcode1
= 0;}
1269 | RESET
{num_op
= 2; opcode0
= 0xD6; opcode1
= 0x10;}
1270 | RET
{num_op
= 2; opcode0
= 0xD6; opcode1
= 0x80;}
1271 | RETI
{num_op
= 2; opcode0
= 0xD6; opcode1
= 0x90;}
1274 BCC
{branch_opcode
= 0xF0;}
1275 | BCS
{branch_opcode
= 0xF1;}
1276 | BEQ
{branch_opcode
= 0xF3;}
1277 | BG
{branch_opcode
= 0xF8;}
1278 | BGE
{branch_opcode
= 0xFA;}
1279 | BGT
{branch_opcode
= 0xFC;}
1280 | BL
{branch_opcode
= 0xF9;}
1281 | BLE
{branch_opcode
= 0xFD;}
1282 | BLT
{branch_opcode
= 0xFB;}
1283 | BMI
{branch_opcode
= 0xF7;}
1284 | BNE
{branch_opcode
= 0xF2;}
1285 | BNV
{branch_opcode
= 0xF4;}
1286 | BOV
{branch_opcode
= 0xF5;}
1287 | BPL
{branch_opcode
= 0xF6;}
1288 | BR
{branch_opcode
= 0xFE;}
1289 | JZ
{branch_opcode
= 0xEC;}
1290 | JNZ
{branch_opcode
= 0xEE;}
1297 int reg
(int reg_spec
)
1299 return reg_spec
& 15;
1302 int reg_indirect
(int reg_spec
)
1304 if
(reg_spec
& BYTE_REG
)
1305 error("Indirect addressing may not use byte registers");
1306 if
((reg_spec
& 15) > 7)
1307 error("Only R0 through R7 may be used for indirect addr");
1308 return reg_spec
& 7;
1311 int rel16
(int pos
, int dest
)
1315 if
(!p3
) return
0; /* don't bother unless writing code */
1316 if
(dest
& (BRANCH_SPACING
- 1))
1317 error("Attempt to jump to unaligned location");
1318 pos
&= ~
(BRANCH_SPACING
- 1);
1319 rel
= (dest
- pos
) / BRANCH_SPACING
;
1320 if
(rel
< -32768 || rel
> 32767)
1321 error("Attempt to jump out of 16 bit relative range");
1322 if
(rel
< 0) rel
+= 65536;
1326 int rel8
(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
< -128 || rel
> 127)
1336 error("Attempt to jump out of 16 bit relative range");
1337 if
(rel
< 0) rel
+= 256;
1343 return
(value
>> 8) & 255;
1351 int direct_addr
(int value
)
1355 if
(value
< 0 || value
> 2047) {
1356 sprintf
(buf
, "illegal value (%d) for direct address", value
);
1362 int imm_data4_signed
(int value
)
1364 if
(value
< -8 || value
> 7)
1365 error("illegal 4 bit (signed) value");
1366 if
(value
>= 0) return value
;
1367 else return
(16 + value
);
1370 int imm_data4_unsigned
(int value
)
1372 if
(value
< 0 || value
> 15)
1373 error("illegal 4 bit (unsigned) value");
1377 int imm_data5_unsigned
(int value
)
1379 if
(value
< 0 || value
> 31)
1380 error("illegal 5 bit (unsigned) value");
1384 int imm_data8
(int value
)
1386 if
(value
< -128 || value
> 255)
1387 error("illegal 8 bit value");
1388 if
(value
>= 0) return value
;
1389 else return
(256 + value
);
1392 int imm_data16
(int value
)
1394 if
(value
< -32728 || value
> 65535)
1395 error("illegal 16 bit value");
1396 if
(value
>= 0) return value
;
1397 else return
(65536 + value
);
1400 int bit_addr
(int value
)
1402 if
(value
< 0 || value
> 1023) {
1403 fprintf
(stderr
, "bad bit addr of 0x%04X (%d dec)\n",
1405 error("illegal bit address");
1411 int find_size_reg
(int op1spec
)
1413 int op1size
=UNKNOWN
;
1415 if
(op1spec
& BYTE_REG
) op1size
= SIZE8
;
1416 if
(op1spec
& WORD_REG
) op1size
= SIZE16
;
1417 if
(op1size
== UNKNOWN
)
1418 error("Register without implied size");
1422 int find_size0
(int isize
)
1424 if
(isize
== UNKNOWN
)
1425 error("Can't determine data size from instruction");
1429 int find_size1
(int isize
, int op1spec
)
1431 int op1size
=UNKNOWN
;
1433 if
(op1spec
& BYTE_REG
) op1size
= SIZE8
;
1434 if
(op1spec
& WORD_REG
) op1size
= SIZE16
;
1435 if
(op1size
== UNKNOWN
)
1436 error("Register without implied size");
1438 if
(isize
== SIZE32
&& op1size
== SIZE16
) return SIZE32
;
1439 if
(isize
== UNKNOWN
) return op1size
;
1441 if
(isize
!= op1size
)
1442 error("data size of register and inst don't agree");
1447 int find_size2
(int isize
, int op1spec
, int op2spec
)
1449 int op1size
=UNKNOWN
, op2size
=UNKNOWN
;
1451 if
(op1spec
& BYTE_REG
) op1size
= SIZE8
;
1452 if
(op1spec
& WORD_REG
) op1size
= SIZE16
;
1453 if
(op1size
== UNKNOWN
)
1454 error("Register without implied size");
1455 if
(op2spec
& BYTE_REG
) op2size
= SIZE8
;
1456 if
(op2spec
& WORD_REG
) op2size
= SIZE16
;
1457 if
(op1size
== UNKNOWN
)
1458 error("Register without implied size");
1460 if
(op1size
!= op2size
)
1461 error("data sizes of two registers don't agree");
1462 if
(isize
== UNKNOWN
) return op1size
;
1464 if
(isize
!= op1size
)
1465 error("data size of registers and inst don't agree");
1470 int yyerror(char *s
)
1472 if
(yytext
[0] >= 32) {
1473 fprintf
(stderr
, "%s near '%s', line %d\n",
1476 fprintf
(stderr
, "%s, line %d\n", s
, lineno
- 1);