diff --git a/src/asm/parser.y b/src/asm/parser.y index 6708d097..907f527b 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -595,6 +595,7 @@ enum { %token T_MODE_HL "hl" T_MODE_HL_DEC "hld/hl-" T_MODE_HL_INC "hli/hl+" %token T_CC_NZ "nz" T_CC_Z "z" T_CC_NC "nc" // There is no T_CC_C, only T_TOKEN_C +%type reg_na %type reg_r %type reg_ss %type reg_rr @@ -1616,6 +1617,7 @@ sectattrs : %empty { cpu_command : T_Z80_LD z80_ld_args + | T_Z80_LD T_MODE_A T_COMMA z80_ld_a_comma_args ; z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> ld pc, pc @@ -1636,7 +1638,7 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> | reg_r T_OP_SUB { // $05,$0D,$15,$1D,$25,$2D,$35,$3D: dec ==> ld - out_AbsByte(0x05 | ($1 << 3)); } - | reg_r T_COMMA reloc_8bit { // $06,$0E,$16,$1E,$26,$2E,$36,$3E: ld , + | reg_na T_COMMA reloc_8bit { // $06,$0E,$16,$1E,$26,$2E,$36: ld , out_AbsByte(0x06 | ($1 << 3)); out_RelByte(&$3, 1); } @@ -1649,9 +1651,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> // $09,$19,$29,$39: add hl, ==> ld hl, hl + out_AbsByte(0x09 | ($5 << 4)); } - | T_MODE_A T_COMMA reg_rr { // $0A,$1A,$2A,$3A: ld a, [] - out_AbsByte(0x0A | ($3 << 4)); - } | reg_ss T_OP_SUB { // $0B,$1B,$2B,$3B: dec ==> ld - out_AbsByte(0x09 | ($1 << 4)); } @@ -1675,13 +1674,7 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> out_AbsByte(0x20 | ($1 << 3)); out_PCRelByte(&$5, 1); } - | T_MODE_A T_COMMA T_MODE_A T_QUESTION { // $27: daa ==> ld a, a? - out_AbsByte(0x27); - } | T_MODE_A T_QUESTION { out_AbsByte(0x27); } // $27: daa ==> ld a? - | T_MODE_A T_COMMA T_OP_NOT T_MODE_A { // $2F: cpl ==> ld a, ~a - out_AbsByte(0x2F); - } | T_OP_NOT T_MODE_A { out_AbsByte(0x2F); } // $2F: cpl ==> ld ~a | T_MODE_F T_PERIOD const_3bit T_COMMA const_1bit { // $37: scf ==> ld f.4, 1 if ($3 != 4) @@ -1698,32 +1691,9 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> else error("Bit field of F must be 4\n"); } - | reg_r T_COMMA reg_r { // $40-$7F: ld , (halt ==> ld [hl], [hl]) + | reg_na T_COMMA reg_r { // $40-$77: ld , (halt ==> ld [hl], [hl]) out_AbsByte(0x40 | ($1 << 3) | $3); } - | T_MODE_A T_COMMA T_MODE_A T_OP_ADD reg_r { // $80-$87: add a, ==> ld a, a + - out_AbsByte(0x80 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_ADD reg_r T_OP_ADD T_TOKEN_C { - // $88-$8F: adc a, ==> ld a, a + + c - out_AbsByte(0x88 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_SUB reg_r { // $90-$97: sub a, ==> ld a, a - - out_AbsByte(0x90 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_SUB reg_r T_OP_SUB T_TOKEN_C { - // $98-$9F: sbc a, ==> ld a, a - - c - out_AbsByte(0x98 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_AND reg_r { // $A0-$A7: and a, ==> ld a, a & - out_AbsByte(0xA0 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_XOR reg_r { // $A8-$AF: xor a, ==> ld a, a ^ - out_AbsByte(0xA8 | $5); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_OR reg_r { // $B0-$B7: or a, ==> ld a, a | - out_AbsByte(0xB0 | $5); - } | T_MODE_F T_PERIOD const_3bit T_COMMA T_MODE_A T_OP_SUB reg_r { // $B8-$BF: cp a, ==> ld f.4, a - if ($3 == 4) @@ -1752,10 +1722,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> | dec_dec_sp_ind T_COMMA reg_tt { // $C5,$D5,$E5,$F5: push ==> ld [--sp], out_AbsByte(0xC5 | ($3 << 4)); } - | T_MODE_A T_COMMA T_MODE_A T_OP_ADD reloc_8bit { // $C6: add a, ==> ld a, a + - out_AbsByte(0xC6); - out_RelByte(&$5, 1); - } | dec_dec_sp_ind T_COMMA T_MODE_PC T_COMMA T_TOKEN_B reloc_16bit { // $C7,$CF,$D7,$DF,$E7,$EF,$F7,$FF: rst ==> ld [--sp], pc, b rpn_CheckRST(&$6, &$6); @@ -1771,15 +1737,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> out_AbsByte(0xCD); out_RelWord(&$5, 1); } - | T_MODE_A T_COMMA T_MODE_A T_OP_ADD T_TOKEN_C T_OP_ADD reloc_8bit { - // $CE: adc a, ==> ld a, a + c + - out_AbsByte(0xCE); - out_RelByte(&$7, 1); - } - | T_MODE_A T_COMMA T_MODE_A T_OP_SUB reloc_8bit { // $D6: sub a, ==> ld a, a - - out_AbsByte(0xD6); - out_RelByte(&$5, 1); - } | T_MODE_PC T_COMMA sp_inc_inc_ind T_OP_DIV T_Z80_LD T_MODE_IME T_COMMA const_1bit { // $D9: reti ==> ld pc, [sp++] / ld ime, 1 if ($8 == 1) @@ -1787,11 +1744,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> else error("LD value of F.4 must be 1\n"); } - | T_MODE_A T_COMMA T_MODE_A T_OP_SUB T_TOKEN_C T_OP_SUB reloc_8bit { - // $DE: sbc a, ==> ld a, a - c - - out_AbsByte(0xDE); - out_RelByte(&$7, 1); - } | T_LBRACK T_TOKEN_H reloc_16bit T_RBRACK T_COMMA T_MODE_A { // $E0: ldh [], a ==> ld [h ], a rpn_CheckHRAM(&$3, &$3); @@ -1801,10 +1753,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> | T_LBRACK T_TOKEN_H T_MODE_C T_RBRACK T_COMMA T_MODE_A { // $E2: ldh [c], a ==> ld [h c], a out_AbsByte(0xE2); } - | T_MODE_A T_COMMA T_MODE_A T_OP_AND reloc_8bit { // $E6: and a, ==> ld a, a & - out_AbsByte(0xE6); - out_RelByte(&$5, 1); - } | T_MODE_SP T_COMMA T_MODE_SP T_OP_ADD reloc_8bit { // $E8: add sp, ==> ld sp, sp+ out_AbsByte(0xE8); out_RelByte(&$5, 1); @@ -1820,27 +1768,9 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> out_RelWord(&$1, 1); } } - | T_MODE_A T_COMMA T_MODE_A T_OP_XOR reloc_8bit { // $EE: xor a, ==> ld a, a ^ - out_AbsByte(0xEE); - out_RelByte(&$5, 1); - } - | T_MODE_A T_COMMA T_LBRACK T_TOKEN_H reloc_16bit T_RBRACK { - // $F0: ldh a, [] ==> ld a, [h ] - rpn_CheckHRAM(&$5, &$5); - out_AbsByte(0xF0); - out_RelByte(&$5, 1); - } - | T_MODE_A T_COMMA T_LBRACK T_TOKEN_H T_MODE_C T_RBRACK { - // $F2: ldh a, [c] ==> ld a, [h c] - out_AbsByte(0xF2); - } | T_MODE_IME T_COMMA const_1bit { // $F3: di ==> ld ime, 0; $FB: ei ==> ld ime, 1 out_AbsByte(0xF3 | ($3 << 3)); } - | T_MODE_A T_COMMA T_MODE_A T_OP_OR reloc_8bit { // $F6: or a, ==> ld a, a | - out_AbsByte(0xF6); - out_RelByte(&$5, 1); - } | T_MODE_HL T_COMMA T_MODE_SP T_OP_ADD reloc_8bit { // $F8: ld hl, sp + out_AbsByte(0xF8); out_RelByte(&$5, 1); @@ -1852,16 +1782,6 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> | T_MODE_SP T_COMMA T_MODE_HL { // $F9: ld sp, hl out_AbsByte(0xF9); } - | T_MODE_A T_COMMA op_mem_ind { // $FA: ld a, [] - if (optimizeloads && rpn_isKnown(&$3) && $3.nVal >= 0xFF00) { - out_AbsByte(0xF0); - out_AbsByte($3.nVal & 0xFF); - rpn_Free(&$3); - } else { - out_AbsByte(0xFA); - out_RelWord(&$3, 1); - } - } | T_MODE_F T_PERIOD const_3bit T_COMMA T_MODE_A T_OP_SUB reloc_8bit { // $FE: cp a, ==> ld f.4, a - if ($3 == 4) { @@ -1871,8 +1791,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Bit field of F must be 4\n"); } } - | reg_r T_COMMA T_PRIME T_PRIME reg_r { - // $CB $00-$07: rlc ==> ld , '' + | reg_na T_COMMA T_PRIME T_PRIME reg_r { + // $CB $00-$06: rlc ==> ld , '' if ($1 == $5) { out_AbsByte(0xCB); out_AbsByte(0x00 | $1); @@ -1880,8 +1800,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA reg_r T_PRIME T_PRIME { - // $CB $08-$0F: rrc ==> ld , '' + | reg_na T_COMMA reg_r T_PRIME T_PRIME { + // $CB $08-$0E: rrc ==> ld , '' if ($1 == $3) { out_AbsByte(0xCB); out_AbsByte(0x08 | $1); @@ -1889,8 +1809,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA T_PRIME reg_r { - // $CB $10-$17: rl ==> ld , ' + | reg_na T_COMMA T_PRIME reg_r { + // $CB $10-$16: rl ==> ld , ' if ($1 == $4) { out_AbsByte(0xCB); out_AbsByte(0x10 | $1); @@ -1898,8 +1818,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA reg_r T_PRIME { - // $CB $18-$1F: rr ==> ld , ' + | reg_na T_COMMA reg_r T_PRIME { + // $CB $18-$1E: rr ==> ld , ' if ($1 == $3) { out_AbsByte(0xCB); out_AbsByte(0x18 | $1); @@ -1907,8 +1827,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA T_OP_SHL reg_r { - // $CB $20-$27: sla ==> ld , << + | reg_na T_COMMA T_OP_SHL reg_r { + // $CB $20-$26: sla ==> ld , << if ($1 == $4) { out_AbsByte(0xCB); out_AbsByte(0x20 | $1); @@ -1916,8 +1836,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA T_OP_SHR reg_r { - // $CB $28-$2F: sra ==> ld , >> + | reg_na T_COMMA T_OP_SHR reg_r { + // $CB $28-$2E: sra ==> ld , >> if ($1 == $4) { out_AbsByte(0xCB); out_AbsByte(0x28 | $1); @@ -1925,8 +1845,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA T_PRIME T_PRIME reg_r T_PRIME T_PRIME { - // $CB $30-$37: swap ==> ld , '''' + | reg_na T_COMMA T_PRIME T_PRIME reg_r T_PRIME T_PRIME { + // $CB $30-$36: swap ==> ld , '''' if ($1 == $5) { out_AbsByte(0xCB); out_AbsByte(0x30 | $1); @@ -1934,8 +1854,8 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> error("Destination and source registers must match\n"); } } - | reg_r T_COMMA T_OP_SHRL reg_r { - // $CB $38-$3F: srl ==> ld , >>> + | reg_na T_COMMA T_OP_SHRL reg_r { + // $CB $38-$3E: srl ==> ld , >>> if ($1 == $4) { out_AbsByte(0xCB); out_AbsByte(0x38 | $1); @@ -1960,6 +1880,117 @@ z80_ld_args : T_MODE_PC T_COMMA T_MODE_PC { out_AbsByte(0x00); } // $00: nop ==> } ; +z80_ld_a_comma_args : reg_rr { // $0A,$1A,$2A,$3A: ld a, [] + out_AbsByte(0x0A | ($1 << 4)); + } + | T_MODE_A T_QUESTION { out_AbsByte(0x27); } // $27: daa ==> ld a, a? + | T_OP_NOT T_MODE_A { out_AbsByte(0x2F); } // $2F: cpl ==> ld a, ~a + | reloc_8bit { // $3E: ld a, + out_AbsByte(0x3E); + out_RelByte(&$1, 1); + } + | reg_r { out_AbsByte(0x78 | $1); } // $78-$7F: ld a, + | T_MODE_A T_OP_ADD reg_r { // $80-$87: add a, ==> ld a, a + + out_AbsByte(0x80 | $3); + } + | T_MODE_A T_OP_ADD reg_r T_OP_ADD T_TOKEN_C { // $88-$8F: adc a, ==> ld a, a + + c + out_AbsByte(0x88 | $3); + } + | T_MODE_A T_OP_SUB reg_r { // $90-$97: sub a, ==> ld a, a - + out_AbsByte(0x90 | $3); + } + | T_MODE_A T_OP_SUB reg_r T_OP_SUB T_TOKEN_C { // $98-$9F: sbc a, ==> ld a, a - - c + out_AbsByte(0x98 | $3); + } + | T_MODE_A T_OP_AND reg_r { // $A0-$A7: and a, ==> ld a, a & + out_AbsByte(0xA0 | $3); + } + | T_MODE_A T_OP_XOR reg_r { // $A8-$AF: xor a, ==> ld a, a ^ + out_AbsByte(0xA8 | $3); + } + | T_MODE_A T_OP_OR reg_r { // $B0-$B7: or a, ==> ld a, a | + out_AbsByte(0xB0 | $3); + } + | T_MODE_A T_OP_ADD reloc_8bit { // $C6: add a, ==> ld a, a + + out_AbsByte(0xC6); + out_RelByte(&$3, 1); + } + | T_MODE_A T_OP_ADD T_TOKEN_C T_OP_ADD reloc_8bit { // $CE: adc a, ==> ld a, a + c + + out_AbsByte(0xCE); + out_RelByte(&$5, 1); + } + | T_MODE_A T_OP_SUB reloc_8bit { // $D6: sub a, ==> ld a, a - + out_AbsByte(0xD6); + out_RelByte(&$3, 1); + } + | T_MODE_A T_OP_SUB T_TOKEN_C T_OP_SUB reloc_8bit { // $DE: sbc a, ==> ld a, a - c - + out_AbsByte(0xDE); + out_RelByte(&$5, 1); + } + | T_MODE_A T_OP_AND reloc_8bit { // $E6: and a, ==> ld a, a & + out_AbsByte(0xE6); + out_RelByte(&$3, 1); + } + | T_MODE_A T_OP_XOR reloc_8bit { // $EE: xor a, ==> ld a, a ^ + out_AbsByte(0xEE); + out_RelByte(&$3, 1); + } + | T_LBRACK T_TOKEN_H reloc_16bit T_RBRACK { // $F0: ldh a, [] ==> ld a, [h ] + rpn_CheckHRAM(&$3, &$3); + out_AbsByte(0xF0); + out_RelByte(&$3, 1); + } + | T_LBRACK T_TOKEN_H T_MODE_C T_RBRACK { // $F2: ldh a, [c] ==> ld a, [h c] + out_AbsByte(0xF2); + } + | T_MODE_A T_OP_OR reloc_8bit { // $F6: or a, ==> ld a, a | + out_AbsByte(0xF6); + out_RelByte(&$3, 1); + } + | op_mem_ind { // $FA: ld a, [] + if (optimizeloads && rpn_isKnown(&$1) && $1.nVal >= 0xFF00) { + out_AbsByte(0xF0); + out_AbsByte($1.nVal & 0xFF); + rpn_Free(&$1); + } else { + out_AbsByte(0xFA); + out_RelWord(&$1, 1); + } + } + | T_PRIME T_PRIME T_MODE_A { // $CB $07: rlc a ==> ld a, ''a + out_AbsByte(0xCB); + out_AbsByte(0x07); + } + | T_MODE_A T_PRIME T_PRIME { // $CB $0F: rrc a ==> ld a, a'' + out_AbsByte(0xCB); + out_AbsByte(0x0F); + } + | T_PRIME T_MODE_A { // $CB $17: rl a ==> ld a, 'a + out_AbsByte(0xCB); + out_AbsByte(0x17); + } + | T_MODE_A T_PRIME { // $CB $1F: rr a ==> ld a, a' + out_AbsByte(0xCB); + out_AbsByte(0x1F); + } + | T_OP_SHL T_MODE_A { // $CB $27: sla a ==> ld a, << a + out_AbsByte(0xCB); + out_AbsByte(0x27); + } + | T_OP_SHR T_MODE_A { // $CB $2F: sra a ==> ld a, >> a + out_AbsByte(0xCB); + out_AbsByte(0x2F); + } + | T_PRIME T_PRIME T_MODE_A T_PRIME T_PRIME { // $CB $37: swap a ==> ld a, ''a'' + out_AbsByte(0xCB); + out_AbsByte(0x37); + } + | T_OP_SHRL T_MODE_A { // $CB $3F: srl a ==> ld a, >>> a + out_AbsByte(0xCB); + out_AbsByte(0x3F); + } +; + op_mem_ind : T_LBRACK reloc_16bit T_RBRACK { $$ = $2; } ; @@ -2001,13 +2032,16 @@ ccode : T_CC_NZ { $$ = CC_NZ; } | T_TOKEN_C { $$ = CC_C; } ; -reg_r : T_MODE_B { $$ = REG_B; } +reg_na : T_MODE_B { $$ = REG_B; } | T_MODE_C { $$ = REG_C; } | T_MODE_D { $$ = REG_D; } | T_MODE_E { $$ = REG_E; } | T_MODE_H { $$ = REG_H; } | T_MODE_L { $$ = REG_L; } | T_LBRACK T_MODE_HL T_RBRACK { $$ = REG_HL_IND; } +; + +reg_r : reg_na | T_MODE_A { $$ = REG_A; } ;