diff --git a/src/zvm_m65/z80_instr_io.s b/src/zvm_m65/z80_instr_io.s index b47beb0b..95ba655d 100644 --- a/src/zvm_m65/z80_instr_io.s +++ b/src/zvm_m65/z80_instr_io.s @@ -23,7 +23,7 @@ Z80_instr_DB: ; sta .REGn tax lda REG_F - and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_PF - Z80_NF) + and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_PF - Z80_NF - Z80_XF - Z80_YF) ora z80_ftable_IN_OR_XOR, x sta REG_F jmp ZVM_next diff --git a/src/zvm_m65/z80_instr_math_8bit.s b/src/zvm_m65/z80_instr_math_8bit.s index b0ee1343..112a79d8 100644 --- a/src/zvm_m65/z80_instr_math_8bit.s +++ b/src/zvm_m65/z80_instr_math_8bit.s @@ -3,15 +3,406 @@ ; Z80 arithmetic instructions, 8 bit ; -; XXX put ADD instructions here -; XXX put SUB instructions here -; XXX put SBC instructions here +; XXX possible optimizations in this fie: special version for ADD/SUB/CP with self, falltrough optimizations in SUB, ADD, CP + +!macro Z80_ADD_n { + jsr (VEC_fetch_value) + bra Z80_common_add +} + +!macro Z80_ADC_n { + jsr (VEC_fetch_value) + bbs0 REG_F,Z80_common_adc + jmp Z80_common_add +} + +!macro Z80_ADD_REGn .REGn { + lda .REGn + bra Z80_common_add +} + +!macro Z80_ADC_REGn .REGn { + lda .REGn + bbs0 REG_F,Z80_common_adc + jmp Z80_common_add +} + +!macro Z80_ADD_VIA_HL { + jsr (VEC_fetch_via_HL) + bra Z80_common_add +} + +!macro Z80_ADC_VIA_HL { + jsr (VEC_fetch_via_HL) + bbs0 REG_F,Z80_common_adc + jmp Z80_common_add +} + +!macro Z80_ADD_VIA_IX_d { + jsr (VEC_fetch_via_IX_d) + bra Z80_common_add +} + +!macro Z80_ADC_VIA_IX_d { + jsr (VEC_fetch_via_IX_d) + bbs0 REG_F,Z80_common_adc + jmp Z80_common_add +} + +!macro Z80_ADD_VIA_IY_d { + jsr (VEC_fetch_via_IY_d) + bra Z80_common_add +} + +!macro Z80_ADC_VIA_IY_d { + jsr (VEC_fetch_via_IY_d) + bbs0 REG_F,Z80_common_adc + jmp Z80_common_add +} + +Z80_instr_C6: +Z80_ADD_n ; ADD A,n +Z80_instr_80: +Z80_ADD_REGn REG_B ; ADD A,B +Z80_instr_81: +Z80_ADD_REGn REG_C ; ADD A,C +Z80_instr_82: +Z80_ADD_REGn REG_D ; ADD A,D +Z80_instr_83: +Z80_ADD_REGn REG_E ; ADD A,E +Z80_instr_84: +Z80_ADD_REGn REG_H ; ADD A,H +Z80_instr_85: +Z80_ADD_REGn REG_L ; ADD A,L +Z80_instr_87: +Z80_ADD_REGn REG_A ; ADD A,A +Z80_illeg_DD_84: +Z80_ADD_REGn REG_IXH ; ADD A,IXH +Z80_illeg_DD_85: +Z80_ADD_REGn REG_IXL ; ADD A,IXL +Z80_illeg_FD_84: +Z80_ADD_REGn REG_IYH ; ADD A,IYH +Z80_illeg_FD_85: +Z80_ADD_REGn REG_IYL ; ADD A,IYL +Z80_instr_86: +Z80_ADD_VIA_HL ; ADD A,(HL) +Z80_instr_DD_86: +Z80_ADD_VIA_IX_d ; ADD A,(IX+d) +Z80_instr_FD_86: +Z80_ADD_VIA_IY_d ; ADD A,(IY+d) + +Z80_common_add: + + sta REG_TMP1 + and #$0F ; calculate half-carry flag + sta REG_TMP2 + lda REG_A + and #$0F + clc + adc REG_TMP2 + and #$F0 + beq @1 + lda #Z80_HF +@1: + sta REG_F ; now REG_F has HF set properly, everything else cleared + lda REG_TMP1 + clc + adc REG_A + sta REG_A + tax + lda REG_F + ora z80_ftable_ADD_ADC, x + sta REG_F + bvs @V1: +@V0: + bcs @VxC1 +@V0C0: + jmp ZVM_next +@VxC1: + +Z80_PUT_1_CF + jmp ZVM_next +@V1: + +Z80_PUT_1_VF + bcs @VxC1 +@V1C0: + jmp ZVM_next + +Z80_instr_CE: +Z80_ADC_n ; ADC A,n +Z80_instr_88: +Z80_ADC_REGn REG_B ; ADC A,B +Z80_instr_89: +Z80_ADC_REGn REG_C ; ADC A,C +Z80_instr_8A: +Z80_ADC_REGn REG_D ; ADC A,D +Z80_instr_8B: +Z80_ADC_REGn REG_E ; ADC A,E +Z80_instr_8C: +Z80_ADC_REGn REG_H ; ADC A,H +Z80_instr_8D: +Z80_ADC_REGn REG_L ; ADC A,L +Z80_instr_8F: +Z80_ADC_REGn REG_A ; ADC A,A +Z80_illeg_DD_8C: +Z80_ADC_REGn REG_IXH ; ADC A,IXH +Z80_illeg_DD_8D: +Z80_ADC_REGn REG_IXL ; ADC A,IXL +Z80_illeg_FD_8C: +Z80_ADC_REGn REG_IYH ; ADC A,IYH +Z80_illeg_FD_8D: +Z80_ADC_REGn REG_IYL ; ADC A,IYL +Z80_instr_8E: +Z80_ADC_VIA_HL ; ADC A,(HL) +Z80_instr_DD_8E: +Z80_ADC_VIA_IX_d ; ADC A,(IX+d) +Z80_instr_FD_8E: +Z80_ADC_VIA_IY_d ; ADC A,(IY+d) + +Z80_common_adc: + + sta REG_TMP1 + and #$0F ; calculate half-carry flag + sta REG_TMP2 + lda REG_A + and #$0F + sec + adc REG_TMP2 + and #$F0 + beq @1 + lda #Z80_HF +@1: + sta REG_F ; now REG_F has HF set properly, everything else cleared + lda REG_TMP1 + sec + adc REG_A + sta REG_A + tax + lda REG_F + ora z80_ftable_ADD_ADC, x + sta REG_F + bvs @V1: +@V0: + bcs @VxC1 +@V0C0: + jmp ZVM_next +@VxC1: + +Z80_PUT_1_CF + jmp ZVM_next +@V1: + +Z80_PUT_1_VF + bcs @VxC1 +@V1C0: + jmp ZVM_next + +!macro Z80_SUB_n { + jsr (VEC_fetch_value) + bra Z80_common_sub +} + +!macro Z80_SBC_n { + jsr (VEC_fetch_value) + bbs0 REG_F,Z80_common_sbc + jmp Z80_common_sub +} + +!macro Z80_SUB_REGn .REGn { + lda .REGn + bra Z80_common_sub +} + +!macro Z80_SBC_REGn .REGn { + lda .REGn + bbs0 REG_F,Z80_common_sbc + jmp Z80_common_sub +} + +!macro Z80_SUB_VIA_HL { + jsr (VEC_fetch_via_HL) + bra Z80_common_sub +} + +!macro Z80_SBC_VIA_HL { + jsr (VEC_fetch_via_HL) + bbs0 REG_F,Z80_common_sbc + jmp Z80_common_sub +} + +!macro Z80_SUB_VIA_IX_d { + jsr (VEC_fetch_via_IX_d) + bra Z80_common_sub +} + +!macro Z80_SBC_VIA_IX_d { + jsr (VEC_fetch_via_IX_d) + bbs0 REG_F,Z80_common_sbc + jmp Z80_common_sub +} + +!macro Z80_SUB_VIA_IY_d { + jsr (VEC_fetch_via_IY_d) + bra Z80_common_sub +} + +!macro Z80_SBC_VIA_IY_d { + jsr (VEC_fetch_via_IY_d) + bbs0 REG_F,Z80_common_sbc + jmp Z80_common_sub +} + +Z80_instr_D6: +Z80_SUB_n ; SUB A,n +Z80_instr_90: +Z80_SUB_REGn REG_B ; SUB A,B +Z80_instr_91: +Z80_SUB_REGn REG_C ; SUB A,C +Z80_instr_92: +Z80_SUB_REGn REG_D ; SUB A,D +Z80_instr_93: +Z80_SUB_REGn REG_E ; SUB A,E +Z80_instr_94: +Z80_SUB_REGn REG_H ; SUB A,H +Z80_instr_95: +Z80_SUB_REGn REG_L ; SUB A,L +Z80_instr_97: +Z80_SUB_REGn REG_A ; SUB A,A +Z80_illeg_DD_94: +Z80_SUB_REGn REG_IXH ; SUB A,IXH +Z80_illeg_DD_95: +Z80_SUB_REGn REG_IXL ; SUB A,IXL +Z80_illeg_FD_94: +Z80_SUB_REGn REG_IYH ; SUB A,IYH +Z80_illeg_FD_95: +Z80_SUB_REGn REG_IYL ; SUB A,IYL +Z80_instr_96: +Z80_SUB_VIA_HL ; SUB A,(HL) +Z80_instr_DD_96: +Z80_SUB_VIA_IX_d ; SUB A,(IX+d) +Z80_instr_FD_96: +Z80_SUB_VIA_IY_d ; SUB A,(IY+d) + +Z80_common_sub: + + sta REG_TMP1 + and #$0F ; calculate half-carry flag + sta REG_TMP2 + lda REG_A + and #$0F + sec + sbc REG_TMP2 + and #$F0 + beq @1 + lda #Z80_HF +@1: + sta REG_F ; now REG_F has HF set properly, everything else cleared + lda REG_TMP1 + sec + sbc REG_A + sta REG_A + tax + lda REG_F + ora z80_ftable_SUB_SBC, x + sta REG_F + bvs @V1: +@V0: + bcc @VxC1 +@V0C0: + jmp ZVM_next +@VxC1: + +Z80_PUT_1_CF + jmp ZVM_next +@V1: + +Z80_PUT_1_VF + bcc @VxC1 +@V1C0: + jmp ZVM_next + +Z80_instr_DE: +Z80_SBC_n ; SBC A,n +Z80_instr_98: +Z80_SBC_REGn REG_B ; SBC A,B +Z80_instr_99: +Z80_SBC_REGn REG_C ; SBC A,C +Z80_instr_9A: +Z80_SBC_REGn REG_D ; SBC A,D +Z80_instr_9B: +Z80_SBC_REGn REG_E ; SBC A,E +Z80_instr_9C: +Z80_SBC_REGn REG_H ; SBC A,H +Z80_instr_9D: +Z80_SBC_REGn REG_L ; SBC A,L +Z80_instr_9F: +Z80_SBC_REGn REG_A ; SBC A,A +Z80_illeg_DD_9C: +Z80_SBC_REGn REG_IXH ; SBC A,IXH +Z80_illeg_DD_9D: +Z80_SBC_REGn REG_IXL ; SBC A,IXL +Z80_illeg_FD_9C: +Z80_SBC_REGn REG_IYH ; SBC A,IYH +Z80_illeg_FD_9D: +Z80_SBC_REGn REG_IYL ; SBC A,IYL +Z80_instr_9E: +Z80_SBC_VIA_HL ; SBC A,(HL) +Z80_instr_DD_9E: +Z80_SBC_VIA_IX_d ; SBC A,(IX+d) +Z80_instr_FD_9E: +Z80_SBC_VIA_IY_d ; SBC A,(IY+d) + +Z80_common_sbc: + + sta REG_TMP1 + and #$0F ; calculate half-carry flag + sta REG_TMP2 + lda REG_A + and #$0F + clc + sbc REG_TMP2 + and #$F0 + beq @1 + lda #Z80_HF +@1: + sta REG_F ; now REG_F has HF set properly, everything else cleared + lda REG_TMP1 + clc + sbc REG_A + sta REG_A + tax + lda REG_F + ora z80_ftable_SUB_SBC, x + sta REG_F + bvs @V1: +@V0: + bcc @VxC1 +@V0C0: + jmp ZVM_next +@VxC1: + +Z80_PUT_1_CF + jmp ZVM_next +@V1: + +Z80_PUT_1_VF + bcc @VxC1 +@V1C0: + jmp ZVM_next + +!macro Z80_CP_n { + jsr (VEC_fetch_value) + bra Z80_common_cp +} + +!macro Z80_CP_REGn .REGn { + lda .REGn + bra Z80_common_cp +} + +!macro Z80_CP_VIA_HL { + jsr (VEC_fetch_via_HL) + bra Z80_common_cp +} + +!macro Z80_CP_VIA_IX_d { + jsr (VEC_fetch_via_IX_d) + bra Z80_common_cp +} + +!macro Z80_CP_VIA_IY_d { + jsr (VEC_fetch_via_IY_d) + bra Z80_common_cp +} + +Z80_instr_FE: +Z80_CP_n ; CP n +Z80_instr_B8: +Z80_CP_REGn REG_B ; CP B +Z80_instr_B9: +Z80_CP_REGn REG_C ; CP C +Z80_instr_BA: +Z80_CP_REGn REG_D ; CP D +Z80_instr_BB: +Z80_CP_REGn REG_E ; CP E +Z80_instr_BC: +Z80_CP_REGn REG_H ; CP H +Z80_instr_BD: +Z80_CP_REGn REG_L ; CP L +Z80_instr_BF: +Z80_CP_REGn REG_A ; CP A +Z80_illeg_DD_BC: +Z80_CP_REGn REG_IXH ; CP IXH +Z80_illeg_DD_BD: +Z80_CP_REGn REG_IXL ; CP IXL +Z80_illeg_FD_BC: +Z80_CP_REGn REG_IYH ; CP IYH +Z80_illeg_FD_BD: +Z80_CP_REGn REG_IYL ; CP IYL +Z80_instr_BE: +Z80_CP_VIA_HL ; CP (HL) +Z80_instr_DD_BE: +Z80_CP_VIA_IX_d ; CP (IX+d) +Z80_instr_FD_BE: +Z80_CP_VIA_IY_d ; CP (IY+d) + +Z80_common_cp: + + sta REG_TMP1 + and #$0F ; calculate half-carry flag + sta REG_TMP2 + lda REG_A + and #$0F + sec + sbc REG_TMP2 + and #$F0 + beq @1 + lda #Z80_HF +@1: + sta REG_F ; now REG_F has HF set properly, everything else cleared + lda REG_TMP1 + sec + sbc REG_A + tax + and #%00101000 + ora z80_ftable_CP, x + sta REG_F + bvs @V1: +@V0: + bcc @VxC1 +@V0C0: + jmp ZVM_next +@VxC1: + +Z80_PUT_1_CF + jmp ZVM_next +@V1: + +Z80_PUT_1_VF + bcc @VxC1 +@V1C0: + jmp ZVM_next + !macro Z80_AND_common_int { - lda REG_F - and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_PF - Z80_NF - Z80_CF) - ora z80_ftable_AND, x + lda z80_ftable_AND, x sta REG_F jmp ZVM_next } @@ -71,9 +462,7 @@ Z80_instr_DD_A6: +Z80_AND_VIA_IX_d ; Z80_instr_FD_A6: +Z80_AND_VIA_IY_d ; AND (IY+d) !macro Z80_OR_XOR_common_int { - lda REG_F - and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_PF - Z80_NF - Z80_CF) - ora z80_ftable_IN_OR_XOR, x + lda z80_ftable_IN_OR_XOR, x sta REG_F jmp ZVM_next } @@ -148,9 +537,7 @@ Z80_instr_FD_B6: +Z80_OR_VIA_IY_d ; !macro Z80_XOR_SELF { lda #$00 sta REG_A - lda REG_F - and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_PF - Z80_NF - Z80_CF) - ora z80_ftable_IN_OR_XOR + lda z80_ftable_IN_OR_XOR sta REG_F jmp ZVM_next } @@ -218,7 +605,7 @@ Z80_instr_3C: ; Z80_common_INC: lda REG_F - and #(0xFF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF) + and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF) ora z80_ftable_INC, x sta REG_F jmp ZVM_next @@ -274,7 +661,7 @@ Z80_instr_3D: ; Z80_common_DEC: lda REG_F - and #(0xFF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF) + and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF) ora z80_ftable_DEC, x sta REG_F jmp ZVM_next diff --git a/src/zvm_m65/z80_instr_rotate_shift.s b/src/zvm_m65/z80_instr_rotate_shift.s index 8db3c5af..e75efea2 100644 --- a/src/zvm_m65/z80_instr_rotate_shift.s +++ b/src/zvm_m65/z80_instr_rotate_shift.s @@ -7,10 +7,14 @@ Z80_instr_07: ; RLCA lda REG_F - and #($FF - Z80_HF - Z80_NF - Z80_CF) + and #($FF - Z80_HF - Z80_NF - Z80_CF - Z80_XF - Z80_YF) sta REG_F asl REG_A + lda REG_A + and #%00101000 + ora REG_F + sta REG_F +bcc ZVM_next inc REG_A +Z80_PUT_1_CF @@ -19,7 +23,7 @@ Z80_instr_07: ; RLCA Z80_instr_17: ; RLA lda REG_F - and #($FF - Z80_HF - Z80_NF - Z80_CF) + and #($FF - Z80_HF - Z80_NF - Z80_CF - Z80_XF - Z80_YF) sta REG_F clc @@ -27,6 +31,10 @@ Z80_instr_17: ; RLA sec @1: rol REG_A + lda REG_A + and #%00101000 + ora REG_F + sta REG_F +bcc ZVM_next +Z80_PUT_1_CF jmp ZVM_next @@ -34,11 +42,15 @@ Z80_instr_17: ; RLA Z80_instr_0F: ; RRCA lda REG_F - and #($FF - Z80_HF - Z80_NF - Z80_CF) + and #($FF - Z80_HF - Z80_NF - Z80_CF - Z80_XF - Z80_YF) sta REG_F clc ror REG_A + lda REG_A + and #%00101000 + ora REG_F + sta REG_F +bcc ZVM_next smb7 REG_A +Z80_PUT_1_CF @@ -47,7 +59,7 @@ Z80_instr_0F: ; RRCA Z80_instr_1F: ; RRA lda REG_F - and #($FF - Z80_HF - Z80_NF - Z80_CF) + and #($FF - Z80_HF - Z80_NF - Z80_CF - Z80_XF - Z80_YF) sta REG_F clc @@ -55,7 +67,197 @@ Z80_instr_1F: ; RRA sec @1: ror REG_A + lda REG_A + and #%00101000 + ora REG_F + sta REG_F +bcc ZVM_next +Z80_PUT_1_CF jmp ZVM_next + +!macro Z80_RLC_REGn .REGn { + + clc + bbr7 .REGn, @1 + sec +@1: + rol .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_00: +Z80_RLC_REGn REG_B ; RLC B +Z80_instr_CB_01: +Z80_RLC_REGn REG_C ; RLC C +Z80_instr_CB_02: +Z80_RLC_REGn REG_D ; RLC D +Z80_instr_CB_03: +Z80_RLC_REGn REG_E ; RLC E +Z80_instr_CB_04: +Z80_RLC_REGn REG_H ; RLC H +Z80_instr_CB_05: +Z80_RLC_REGn REG_L ; RLC L +Z80_instr_CB_07: +Z80_RLC_REGn REG_A ; RLC A + +!macro Z80_RRC_REGn .REGn { + + clc + bbr0 .REGn, @1 + sec +@1: + ror .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_08: +Z80_RRC_REGn REG_B ; RRC B +Z80_instr_CB_09: +Z80_RRC_REGn REG_C ; RRC C +Z80_instr_CB_0A: +Z80_RRC_REGn REG_D ; RRC D +Z80_instr_CB_0B: +Z80_RRC_REGn REG_E ; RRC E +Z80_instr_CB_0C: +Z80_RRC_REGn REG_H ; RRC H +Z80_instr_CB_0D: +Z80_RRC_REGn REG_L ; RRC L +Z80_instr_CB_0F: +Z80_RRC_REGn REG_A ; RRC A + +!macro Z80_RL_REGn .REGn { + + clc + bbr0 REG_F, @1 + sec +@1: + rol .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_10: +Z80_RL_REGn REG_B ; RL B +Z80_instr_CB_11: +Z80_RL_REGn REG_C ; RL C +Z80_instr_CB_12: +Z80_RL_REGn REG_D ; RL D +Z80_instr_CB_13: +Z80_RL_REGn REG_E ; RL E +Z80_instr_CB_14: +Z80_RL_REGn REG_H ; RL H +Z80_instr_CB_15: +Z80_RL_REGn REG_L ; RL L +Z80_instr_CB_17: +Z80_RL_REGn REG_A ; RL A + +!macro Z80_RR_REGn .REGn { + + clc + bbr0 REG_F, @1 + sec +@1: + ror .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_18: +Z80_RR_REGn REG_B ; RR B +Z80_instr_CB_19: +Z80_RR_REGn REG_C ; RR C +Z80_instr_CB_1A: +Z80_RR_REGn REG_D ; RR D +Z80_instr_CB_1B: +Z80_RR_REGn REG_E ; RR E +Z80_instr_CB_1C: +Z80_RR_REGn REG_H ; RR H +Z80_instr_CB_1D: +Z80_RR_REGn REG_L ; RR L +Z80_instr_CB_1F: +Z80_RR_REGn REG_A ; RR A + +; XXX SLA/SLL (and possibly rotations) can be made slightly faster with dedicated tables (omit carry flag calculation) + +!macro Z80_SLA_REGn .REGn { + + asl .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_20: +Z80_SLA_REGn REG_B ; SLA B +Z80_instr_CB_21: +Z80_SLA_REGn REG_C ; SLA C +Z80_instr_CB_22: +Z80_SLA_REGn REG_D ; SLA D +Z80_instr_CB_23: +Z80_SLA_REGn REG_E ; SLA E +Z80_instr_CB_24: +Z80_SLA_REGn REG_H ; SLA H +Z80_instr_CB_25: +Z80_SLA_REGn REG_L ; SLA L +Z80_instr_CB_27: +Z80_SLA_REGn REG_A ; SLA A + +!macro Z80_SLL_REGn .REGn { + + sec + rol .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_illeg_CB_30: +Z80_SLL_REGn REG_B ; SLL B +Z80_illeg_CB_31: +Z80_SLL_REGn REG_C ; SLL C +Z80_illeg_CB_32: +Z80_SLL_REGn REG_D ; SLL D +Z80_illeg_CB_33: +Z80_SLL_REGn REG_E ; SLL E +Z80_illeg_CB_34: +Z80_SLL_REGn REG_H ; SLL H +Z80_illeg_CB_35: +Z80_SLL_REGn REG_L ; SLL L +Z80_illeg_CB_37: +Z80_SLL_REGn REG_A ; SLL A + +!macro Z80_SRL_REGn .REGn { + + clc + ror .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_38: +Z80_SRL_REGn REG_B ; SRL B +Z80_instr_CB_39: +Z80_SRL_REGn REG_C ; SRL C +Z80_instr_CB_3A: +Z80_SRL_REGn REG_D ; SRL D +Z80_instr_CB_3B: +Z80_SRL_REGn REG_E ; SRL E +Z80_instr_CB_3C: +Z80_SRL_REGn REG_H ; SRL H +Z80_instr_CB_3D: +Z80_SRL_REGn REG_L ; SRL L +Z80_instr_CB_3F: +Z80_SRL_REGn REG_A ; SRL A + +!macro Z80_SRA_REGn .REGn { + + clc + bbr7 .REGn, @1 + sec +@1: + ror .REGn + + ldx .REGn + lda z80_ftable_IN_OR_XOR, x + sta REG_F + +bcc ZVM_next + +Z80_PUT_1_CF + jmp ZVM_next +} + +Z80_instr_CB_28: +Z80_SRA_REGn REG_B; SRA B +Z80_instr_CB_29: +Z80_SRA_REGn REG_C; SRA C +Z80_instr_CB_2A: +Z80_SRA_REGn REG_D; SRA D +Z80_instr_CB_2B: +Z80_SRA_REGn REG_E; SRA E +Z80_instr_CB_2C: +Z80_SRA_REGn REG_H; SRA H +Z80_instr_CB_2D: +Z80_SRA_REGn REG_L; SRA L +Z80_instr_CB_2F: +Z80_SRA_REGn REG_A; SRA A + + diff --git a/src/zvm_m65/z80_tables.s b/src/zvm_m65/z80_tables.s index a43d6d54..76b6127b 100644 --- a/src/zvm_m65/z80_tables.s +++ b/src/zvm_m65/z80_tables.s @@ -5,98 +5,83 @@ ; z80_ftable_parity: -; ; +PUT_Z80_FTABLE_PARITY - z80_otable_displacement: - +PUT_Z80_OTABLE_DISPLACEMENT z80_ftable_INC: - +PUT_Z80_FTABLE_INC z80_ftable_DEC: - +PUT_Z80_FTABLE_DEC z80_ftable_AND: - +PUT_Z80_FTABLE_AND -z80_ftable_IN_OR_XOR: - +z80_ftable_IN_OR_XOR: ; XXX rename to include shift/rotate +PUT_Z80_FTABLE_IN_OR_XOR z80_ftable_NEG: - +PUT_Z80_FTABLE_NEG +z80_ftable_ADD_ADC: + +PUT_Z80_FTABLE_ADD_ADC + +z80_ftable_SUB_SBC: + +PUT_Z80_FTABLE_SUB_SBC + +z80_ftable_CP: + +PUT_Z80_FTABLE_CP + ; ; That horrific DAA instruction ; z80_otable_DAA_N0C0H0: - +PUT_Z80_OTABLE_DAA_N0C0H0 z80_otable_DAA_N0C0H1: - +PUT_Z80_OTABLE_DAA_N0C0H1 z80_otable_DAA_N0C1H0: - +PUT_Z80_OTABLE_DAA_N0C1H0 z80_otable_DAA_N0C1H1: - +PUT_Z80_OTABLE_DAA_N0C1H1 z80_otable_DAA_N1C0H0: - +PUT_Z80_OTABLE_DAA_N1C0H0 z80_otable_DAA_N1C0H1: - +PUT_Z80_OTABLE_DAA_N1C0H1 z80_otable_DAA_N1C1H0: - +PUT_Z80_OTABLE_DAA_N1C1H0 z80_otable_DAA_N1C1H1: - +PUT_Z80_OTABLE_DAA_N1C1H1 z80_ftable_DAA_N0C0H0: - +PUT_Z80_FTABLE_DAA_N0C0H0 z80_ftable_DAA_N0C0H1: - +PUT_Z80_FTABLE_DAA_N0C0H1 z80_ftable_DAA_N0C1H0: - +PUT_Z80_FTABLE_DAA_N0C1H0 z80_ftable_DAA_N0C1H1: - +PUT_Z80_FTABLE_DAA_N0C1H1 z80_ftable_DAA_N1C0H0: - +PUT_Z80_FTABLE_DAA_N1C0H0 z80_ftable_DAA_N1C0H1: - +PUT_Z80_FTABLE_DAA_N1C0H1 z80_ftable_DAA_N1C1H0: - +PUT_Z80_FTABLE_DAA_N1C1H0 z80_ftable_DAA_N1C1H1: - +PUT_Z80_FTABLE_DAA_N1C1H1 diff --git a/src/zvm_m65/zvm_core.s b/src/zvm_m65/zvm_core.s index 499d677d..eea2a1c5 100644 --- a/src/zvm_m65/zvm_core.s +++ b/src/zvm_m65/zvm_core.s @@ -122,6 +122,7 @@ Z80_instr_FD: +ZVM_DISPATCH Z80_vectab_FD_0, Z80_vectab_FD_1 ; + ; ; Not implemented yet - XXX implement them! ; @@ -135,120 +136,21 @@ Z80_instr_22: ; LD (nn),HL Z80_instr_29: ; ADD HL,HL Z80_instr_2A: ; LD HL,(nn) Z80_instr_39: ; ADD HL,SP -Z80_instr_80: ; ADD A,B -Z80_instr_81: ; ADD A,C -Z80_instr_82: ; ADD A,D -Z80_instr_83: ; ADD A,E -Z80_instr_84: ; ADD A,H -Z80_instr_85: ; ADD A,L -Z80_instr_86: ; ADD A,(HL) -Z80_instr_87: ; ADD A,A -Z80_instr_88: ; ADC A,B -Z80_instr_89: ; ADC A,C -Z80_instr_8A: ; ADC A,D -Z80_instr_8B: ; ADC A,E -Z80_instr_8C: ; ADC A,H -Z80_instr_8D: ; ADC A,L -Z80_instr_8E: ; ADC A,(HL) -Z80_instr_8F: ; ADC A,A -Z80_instr_90: ; SUB B -Z80_instr_91: ; SUB C -Z80_instr_92: ; SUB D -Z80_instr_93: ; SUB E -Z80_instr_94: ; SUB H -Z80_instr_95: ; SUB L -Z80_instr_96: ; SUB (HL) -Z80_instr_97: ; SUB A -Z80_instr_98: ; SBC B -Z80_instr_99: ; SBC C -Z80_instr_9A: ; SBC D -Z80_instr_9B: ; SBC E -Z80_instr_9C: ; SBC H -Z80_instr_9D: ; SBC L -Z80_instr_9E: ; SBC (HL) -Z80_instr_9F: ; SBC A -Z80_instr_B8: ; CP B -Z80_instr_B9: ; CP C -Z80_instr_BA: ; CP D -Z80_instr_BB: ; CP E -Z80_instr_BC: ; CP H -Z80_instr_BD: ; CP L -Z80_instr_BE: ; CP (HL) -Z80_instr_BF: ; CP A -Z80_instr_C6: ; ADD A,n -Z80_instr_CE: ; ADC A,n -Z80_instr_D6: ; SUB n -Z80_instr_DE: ; SBC A,n Z80_instr_E3: ; EX (SP),HL Z80_instr_F9: ; LD SP,HL -Z80_instr_FE: ; CP n -Z80_instr_CB_00: ; RLC B -Z80_instr_CB_01: ; RLC C -Z80_instr_CB_02: ; RLC D -Z80_instr_CB_03: ; RLC E -Z80_instr_CB_04: ; RLC H -Z80_instr_CB_05: ; RLC L Z80_instr_CB_06: ; RLC (HL) -Z80_instr_CB_07: ; RLC A -Z80_instr_CB_08: ; RRC B -Z80_instr_CB_09: ; RRC C -Z80_instr_CB_0A: ; RRC D -Z80_instr_CB_0B: ; RRC E -Z80_instr_CB_0C: ; RRC H -Z80_instr_CB_0D: ; RRC L Z80_instr_CB_0E: ; RRC (HL) -Z80_instr_CB_0F: ; RRC A -Z80_instr_CB_10: ; RL B -Z80_instr_CB_11: ; RL C -Z80_instr_CB_12: ; RL D -Z80_instr_CB_13: ; RL E -Z80_instr_CB_14: ; RL H -Z80_instr_CB_15: ; RL L Z80_instr_CB_16: ; RL (HL) -Z80_instr_CB_17: ; RL A -Z80_instr_CB_18: ; RR B -Z80_instr_CB_19: ; RR C -Z80_instr_CB_1A: ; RR D -Z80_instr_CB_1B: ; RR E -Z80_instr_CB_1C: ; RR H -Z80_instr_CB_1D: ; RR L Z80_instr_CB_1E: ; RR (HL) -Z80_instr_CB_1F: ; RR A -Z80_instr_CB_20: ; SLA B -Z80_instr_CB_21: ; SLA C -Z80_instr_CB_22: ; SLA D -Z80_instr_CB_23: ; SLA E -Z80_instr_CB_24: ; SLA H -Z80_instr_CB_25: ; SLA L Z80_instr_CB_26: ; SLA (HL) -Z80_instr_CB_27: ; SLA A -Z80_instr_CB_28: ; SRA B -Z80_instr_CB_29: ; SRA C -Z80_instr_CB_2A: ; SRA D -Z80_instr_CB_2B: ; SRA E -Z80_instr_CB_2C: ; SRA H -Z80_instr_CB_2D: ; SRA L Z80_instr_CB_2E: ; SRA (HL) -Z80_instr_CB_2F: ; SRA A -Z80_instr_CB_38: ; SRL B -Z80_instr_CB_39: ; SRL C -Z80_instr_CB_3A: ; SRL D -Z80_instr_CB_3B: ; SRL E -Z80_instr_CB_3C: ; SRL H -Z80_instr_CB_3D: ; SRL L Z80_instr_CB_3E: ; SRL (HL) -Z80_instr_CB_3F: ; SRL A Z80_instr_DD_09: ; ADD IX,BC Z80_instr_DD_19: ; ADD IX,DE Z80_instr_DD_22: ; LD (nn),IX Z80_instr_DD_29: ; ADD IX,IX Z80_instr_DD_2A: ; LD IX,(nn) Z80_instr_DD_39: ; ADD IX,SP -Z80_instr_DD_86: ; ADD A,(IX+d) -Z80_instr_DD_8E: ; ADC A,(IX+d) -Z80_instr_DD_96: ; SUB (IX+d) -Z80_instr_DD_9E: ; SBC (IX+d) -Z80_instr_DD_BE: ; CP (IX+d) Z80_instr_DD_E3: ; EX (SP),IX Z80_instr_DD_F9: ; LD SP,IX Z80_instr_ED_42: ; SBC HL,BC @@ -289,11 +191,6 @@ Z80_instr_FD_22: ; LD (nn),IY Z80_instr_FD_29: ; ADD IY,IY Z80_instr_FD_2A: ; LD IY,(nn) Z80_instr_FD_39: ; ADD IY,SP -Z80_instr_FD_86: ; ADD A,(IY+d) -Z80_instr_FD_8E: ; ADC A,(IY+d) -Z80_instr_FD_96: ; SUB (IY+d) -Z80_instr_FD_9E: ; SBC (IY+d) -Z80_instr_FD_BE: ; CP (IY+d) Z80_instr_FD_E3: ; EX (SP),IY Z80_instr_FD_F9: ; LD SP,IY Z80_instr_xDCB_06: ; RLC (IXY+d) @@ -303,38 +200,11 @@ Z80_instr_xDCB_1E: ; RR (IXY+d) Z80_instr_xDCB_26: ; SLA (IXY+d) Z80_instr_xDCB_2E: ; SRA (IXY+d) Z80_instr_xDCB_3E: ; SRL (IXY+d) -Z80_illeg_CB_30: ; SLL B -Z80_illeg_CB_31: ; SLL C -Z80_illeg_CB_32: ; SLL D -Z80_illeg_CB_33: ; SLL E -Z80_illeg_CB_34: ; SLL H -Z80_illeg_CB_35: ; SLL L Z80_illeg_CB_36: ; SLL (HL) -Z80_illeg_CB_37: ; SLL A Z80_illeg_ED_70: ; IN F,(C) Z80_illeg_ED_71: ; OUT (C),0 Z80_illeg_ED_63: ; LD (nn),HL Z80_illeg_ED_6B: ; LD HL,(nn) -Z80_illeg_DD_84: ; ADD A,IXH -Z80_illeg_DD_85: ; ADD A,IXL -Z80_illeg_DD_8C: ; ADC A,IXH -Z80_illeg_DD_8D: ; ADC A,IXL -Z80_illeg_DD_94: ; SUB A,IXH -Z80_illeg_DD_95: ; SUB A,IXL -Z80_illeg_DD_9C: ; SBC A,IXH -Z80_illeg_DD_9D: ; SBC A,IXL -Z80_illeg_DD_BC: ; CP IXH -Z80_illeg_DD_BD: ; CP IXL -Z80_illeg_FD_84: ; ADD A,IYH -Z80_illeg_FD_85: ; ADD A,IYL -Z80_illeg_FD_8C: ; ADC A,IYH -Z80_illeg_FD_8D: ; ADC A,IYL -Z80_illeg_FD_94: ; SUB A,IYH -Z80_illeg_FD_95: ; SUB A,IYL -Z80_illeg_FD_9C: ; SBC A,IYH -Z80_illeg_FD_9D: ; SBC A,IYL -Z80_illeg_FD_BC: ; CP IYH -Z80_illeg_FD_BD: ; CP IYL Z80_illeg_xDCB_00: ; RLC (IXY+d),B Z80_illeg_xDCB_01: ; RLC (IXY+d),C Z80_illeg_xDCB_02: ; RLC (IXY+d),D diff --git a/tools/generate_z80_tables.cc b/tools/generate_z80_tables.cc index c98c7ce9..34e4fd8f 100644 --- a/tools/generate_z80_tables.cc +++ b/tools/generate_z80_tables.cc @@ -186,6 +186,8 @@ std::string generateAndTable(void) uint8_t flags = Z80_HF | GLOBAL_Parity[idx]; if (idx >= 0x80) flags |= Z80_SF; // for negative result if (idx == 0) flags |= Z80_ZF; // for result equal 0 + if (idx & 0x08) flags |= Z80_XF; // 3rd bit of the result + if (idx & 0x20) flags |= Z80_YF; // 5th bit of the result outStr << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << int(flags) << "\n"; } @@ -203,6 +205,63 @@ std::string generateInOrXorTable(void) uint8_t flags = GLOBAL_Parity[idx]; if (idx >= 0x80) flags |= Z80_SF; // for negative result if (idx == 0) flags |= Z80_ZF; // for result equal 0 + if (idx & 0x08) flags |= Z80_XF; // 3rd bit of the result + if (idx & 0x20) flags |= Z80_YF; // 5th bit of the result + + outStr << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << int(flags) << "\n"; + } + + return outStr.str() + "}\n\n\n"; +} + +std::string generateAddAdcTable(void) +{ + std::stringstream outStr; + outStr << "!macro PUT_Z80_FTABLE_ADD_ADC {\n"; + + for (uint16_t idx = 0; idx < 0x100; idx++) + { + uint8_t flags = 0; + if (idx >= 0x80) flags |= Z80_SF; // for negative result + if (idx == 0) flags |= Z80_ZF; // for result equal 0 + if (idx & 0x08) flags |= Z80_XF; // 3rd bit of the result + if (idx & 0x20) flags |= Z80_YF; // 5th bit of the result + + outStr << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << int(flags) << "\n"; + } + + return outStr.str() + "}\n\n\n"; +} + +std::string generateSubSbcTable(void) +{ + std::stringstream outStr; + outStr << "!macro PUT_Z80_FTABLE_SUB_SBC {\n"; + + for (uint16_t idx = 0; idx < 0x100; idx++) + { + uint8_t flags = Z80_NF; + if (idx >= 0x80) flags |= Z80_SF; // for negative result + if (idx == 0) flags |= Z80_ZF; // for result equal 0 + if (idx & 0x08) flags |= Z80_XF; // 3rd bit of the result + if (idx & 0x20) flags |= Z80_YF; // 5th bit of the result + + outStr << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << int(flags) << "\n"; + } + + return outStr.str() + "}\n\n\n"; +} + +std::string generateCpTable(void) +{ + std::stringstream outStr; + outStr << "!macro PUT_Z80_FTABLE_CP {\n"; + + for (uint16_t idx = 0; idx < 0x100; idx++) + { + uint8_t flags = Z80_NF; + if (idx >= 0x80) flags |= Z80_SF; // for negative result + if (idx == 0) flags |= Z80_ZF; // for result equal 0 outStr << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << int(flags) << "\n"; } @@ -353,6 +412,9 @@ void writeTables() outFile << generateDecTable(); outFile << generateAndTable(); outFile << generateInOrXorTable(); + outFile << generateAddAdcTable(); + outFile << generateSubSbcTable(); + outFile << generateCpTable(); outFile << generateNegTable(); outFile << generateDaaTables();