Files
open-roms/src/zvm_m65/z80_instr_math_8bit.s
T

694 lines
19 KiB
ArmAsm

;
; Z80 arithmetic instructions, 8 bit
;
; XXX possible optimizations in this fie: special version for ADD/SUB/CP with self, falltrough optimizations in SUB, ADD, CP
!macro Z80_ADD_n {
+Z80_FETCH_VIA_PC_INC
bra Z80_common_add
}
!macro Z80_ADC_n {
+Z80_FETCH_VIA_PC_INC
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 {
+Z80_FETCH_VIA_HL
bra Z80_common_add
}
!macro Z80_ADC_VIA_HL {
+Z80_FETCH_VIA_HL
bbs0 REG_F,Z80_common_adc
jmp Z80_common_add
}
!macro Z80_ADD_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
bra Z80_common_add
}
!macro Z80_ADC_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
bbs0 REG_F,Z80_common_adc
jmp Z80_common_add
}
!macro Z80_ADD_VIA_IY_d {
+Z80_FETCH_VIA_IY_d
bra Z80_common_add
}
!macro Z80_ADC_VIA_IY_d {
+Z80_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 {
+Z80_FETCH_VIA_PC_INC
bra Z80_common_sub
}
!macro Z80_SBC_n {
+Z80_FETCH_VIA_PC_INC
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 {
+Z80_FETCH_VIA_HL
bra Z80_common_sub
}
!macro Z80_SBC_VIA_HL {
+Z80_FETCH_VIA_HL
bbs0 REG_F,Z80_common_sbc
jmp Z80_common_sub
}
!macro Z80_SUB_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
bra Z80_common_sub
}
!macro Z80_SBC_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
bbs0 REG_F,Z80_common_sbc
jmp Z80_common_sub
}
!macro Z80_SUB_VIA_IY_d {
+Z80_FETCH_VIA_IY_d
bra Z80_common_sub
}
!macro Z80_SBC_VIA_IY_d {
+Z80_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 {
+Z80_FETCH_VIA_PC_INC
bra Z80_common_cp
}
!macro Z80_CP_REGn .REGn {
lda .REGn
bra Z80_common_cp
}
!macro Z80_CP_VIA_HL {
+Z80_FETCH_VIA_HL
bra Z80_common_cp
}
!macro Z80_CP_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
bra Z80_common_cp
}
!macro Z80_CP_VIA_IY_d {
+Z80_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 z80_ftable_AND, x
sta REG_F
jmp ZVM_next
}
!macro Z80_AND_common {
and REG_A
sta REG_A
tax
+Z80_AND_common_int
}
!macro Z80_AND_REGn .REGn {
lda .REGn
+Z80_AND_common
}
!macro Z80_AND_SELF {
ldx REG_A
+Z80_AND_common_int
}
!macro Z80_AND_VIA_HL {
+Z80_FETCH_VIA_HL
+Z80_AND_common
}
!macro Z80_AND_n {
+Z80_FETCH_VIA_PC_INC
+Z80_AND_common
}
!macro Z80_AND_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
+Z80_AND_common
}
!macro Z80_AND_VIA_IY_d {
+Z80_FETCH_VIA_IY_d
+Z80_AND_common
}
Z80_instr_A0: +Z80_AND_REGn REG_B ; AND B
Z80_instr_A1: +Z80_AND_REGn REG_C ; AND C
Z80_instr_A2: +Z80_AND_REGn REG_D ; AND D
Z80_instr_A3: +Z80_AND_REGn REG_E ; AND E
Z80_instr_A4: +Z80_AND_REGn REG_H ; AND H
Z80_instr_A5: +Z80_AND_REGn REG_L ; AND L
Z80_illeg_DD_A4: +Z80_AND_REGn REG_IXH ; AND IXH
Z80_illeg_DD_A5: +Z80_AND_REGn REG_IXL ; AND IXL
Z80_illeg_FD_A4: +Z80_AND_REGn REG_IYH ; AND IYH
Z80_illeg_FD_A5: +Z80_AND_REGn REG_IXL ; AND IYL
Z80_instr_A6: +Z80_AND_VIA_HL ; AND (HL)
Z80_instr_A7: +Z80_AND_SELF ; AND A
Z80_instr_E6: +Z80_AND_n ; AND n
Z80_instr_DD_A6: +Z80_AND_VIA_IX_d ; AND (IX+d)
Z80_instr_FD_A6: +Z80_AND_VIA_IY_d ; AND (IY+d)
!macro Z80_OR_XOR_common_int {
lda z80_ftable_IN_OR_XOR, x
sta REG_F
jmp ZVM_next
}
!macro Z80_OR_common {
ora REG_A
sta REG_A
tax
+Z80_OR_XOR_common_int
}
!macro Z80_OR_REGn .REGn {
lda .REGn
+Z80_OR_common
}
!macro Z80_OR_SELF {
ldx REG_A
+Z80_OR_XOR_common_int
}
!macro Z80_OR_VIA_HL {
+Z80_FETCH_VIA_HL
+Z80_OR_common
}
!macro Z80_OR_n {
+Z80_FETCH_VIA_PC_INC
+Z80_OR_common
}
!macro Z80_OR_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
+Z80_OR_common
}
!macro Z80_OR_VIA_IY_d {
+Z80_FETCH_VIA_IY_d
+Z80_OR_common
}
Z80_instr_B0: +Z80_OR_REGn REG_B ; OR B
Z80_instr_B1: +Z80_OR_REGn REG_C ; OR C
Z80_instr_B2: +Z80_OR_REGn REG_D ; OR D
Z80_instr_B3: +Z80_OR_REGn REG_E ; OR E
Z80_instr_B4: +Z80_OR_REGn REG_H ; OR H
Z80_instr_B5: +Z80_OR_REGn REG_L ; OR L
Z80_illeg_DD_B4: +Z80_OR_REGn REG_IXH ; OR IXH
Z80_illeg_DD_B5: +Z80_OR_REGn REG_IXL ; OR IXL
Z80_illeg_FD_B4: +Z80_OR_REGn REG_IYH ; OR IYH
Z80_illeg_FD_B5: +Z80_OR_REGn REG_IYL ; OR IYL
Z80_instr_B6: +Z80_OR_VIA_HL ; OR (HL)
Z80_instr_B7: +Z80_OR_SELF ; OR A
Z80_instr_F6: +Z80_OR_n ; OR n
Z80_instr_DD_B6: +Z80_OR_VIA_IX_d ; OR (IX+d)
Z80_instr_FD_B6: +Z80_OR_VIA_IY_d ; OR (IY+d)
!macro Z80_XOR_common {
eor REG_A
sta REG_A
tax
+Z80_OR_XOR_common_int
}
!macro Z80_XOR_REGn .REGn {
lda .REGn
+Z80_XOR_common
}
!macro Z80_XOR_SELF {
lda #$00
sta REG_A
lda z80_ftable_IN_OR_XOR
sta REG_F
jmp ZVM_next
}
!macro Z80_XOR_VIA_HL {
+Z80_FETCH_VIA_HL
+Z80_XOR_common
}
!macro Z80_XOR_n {
+Z80_FETCH_VIA_PC_INC
+Z80_XOR_common
}
!macro Z80_XOR_VIA_IX_d {
+Z80_FETCH_VIA_IX_d
+Z80_XOR_common
}
!macro Z80_XOR_VIA_IY_d {
+Z80_FETCH_VIA_IY_d
+Z80_XOR_common
}
Z80_instr_A8: +Z80_XOR_REGn REG_B ; XOR B
Z80_instr_A9: +Z80_XOR_REGn REG_C ; XOR C
Z80_instr_AA: +Z80_XOR_REGn REG_D ; XOR D
Z80_instr_AB: +Z80_XOR_REGn REG_E ; XOR E
Z80_instr_AC: +Z80_XOR_REGn REG_H ; XOR H
Z80_instr_AD: +Z80_XOR_REGn REG_L ; XOR L
Z80_illeg_DD_AC: +Z80_XOR_REGn REG_IXH ; XOR IXH
Z80_illeg_DD_AD: +Z80_XOR_REGn REG_IXL ; XOR IXL
Z80_illeg_FD_AC: +Z80_XOR_REGn REG_IYH ; XOR IYH
Z80_illeg_FD_AD: +Z80_XOR_REGn REG_IXL ; XOR IYL
Z80_instr_AE: +Z80_XOR_VIA_HL ; XOR (HL)
Z80_instr_AF: +Z80_XOR_SELF ; XOR A
Z80_instr_EE: +Z80_XOR_n ; XOR n
Z80_instr_DD_AE: +Z80_XOR_VIA_IX_d ; XOR (IX+d)
Z80_instr_FD_AE: +Z80_XOR_VIA_IY_d ; XOR (IY+d)
!macro Z80_INC_REG_n .REG_n {
ldx .REG_n
inc .REG_n
bra Z80_common_INC
}
Z80_instr_04: +Z80_INC_REG_n REG_B ; INC B
Z80_instr_0C: +Z80_INC_REG_n REG_C ; INC C
Z80_instr_14: +Z80_INC_REG_n REG_D ; INC D
Z80_instr_1C: +Z80_INC_REG_n REG_E ; INC E
Z80_instr_24: +Z80_INC_REG_n REG_H ; INC H
Z80_instr_2C: +Z80_INC_REG_n REG_L ; INC L
Z80_illeg_DD_24: +Z80_INC_REG_n REG_IXH ; INC IXH
Z80_illeg_DD_2C: +Z80_INC_REG_n REG_IXL ; INC IXL
Z80_illeg_FD_24: +Z80_INC_REG_n REG_IYH ; INC IYH
Z80_illeg_FD_2C: +Z80_INC_REG_n REG_IYL ; INC IYL
Z80_instr_3C: ; INC A
ldx REG_A
inc REG_A
; FALLTROUGH
Z80_common_INC:
lda REG_F
and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF)
ora z80_ftable_INC, x
sta REG_F
jmp ZVM_next
Z80_instr_34: ; INC (HL)
+Z80_FETCH_VIA_HL
tax
inc
+Z80_STORE_BACK_VIA_HL
bra Z80_common_INC
Z80_instr_DD_34: ; INC (IX+d)
+Z80_FETCH_VIA_IX_d
tax
inc
sta [PTR_DATA],z
bra Z80_common_INC
Z80_instr_FD_34: ; INC (IY+d)
+Z80_FETCH_VIA_IY_d
tax
inc
sta [PTR_DATA],z
bra Z80_common_INC
!macro Z80_DEC_REG_n .REG_n {
ldx .REG_n
dec .REG_n
bra Z80_common_DEC
}
Z80_instr_05: +Z80_DEC_REG_n REG_B ; DEC B
Z80_instr_0D: +Z80_DEC_REG_n REG_C ; DEC C
Z80_instr_15: +Z80_DEC_REG_n REG_D ; DEC D
Z80_instr_1D: +Z80_DEC_REG_n REG_E ; DEC E
Z80_instr_25: +Z80_DEC_REG_n REG_H ; DEC H
Z80_instr_2D: +Z80_DEC_REG_n REG_L ; DEC L
Z80_illeg_DD_25: +Z80_DEC_REG_n REG_IXH ; DEC IXH
Z80_illeg_DD_2D: +Z80_DEC_REG_n REG_IXL ; DEC IXL
Z80_illeg_FD_25: +Z80_DEC_REG_n REG_IYH ; DEC IYH
Z80_illeg_FD_2D: +Z80_DEC_REG_n REG_IYL ; DEC IYL
Z80_instr_3D: ; DEC A
ldx REG_A
dec REG_A
; FALLTROUGH
Z80_common_DEC:
lda REG_F
and #($FF - Z80_SF - Z80_ZF - Z80_HF - Z80_VF - Z80_NF)
ora z80_ftable_DEC, x
sta REG_F
jmp ZVM_next
Z80_instr_35: ; DEC (HL)
+Z80_FETCH_VIA_HL
tax
dec
+Z80_STORE_BACK_VIA_HL
bra Z80_common_DEC
Z80_instr_DD_35: ; DEC (IX+d)
+Z80_FETCH_VIA_IX_d
tax
dec
sta [PTR_DATA],z
bra Z80_common_DEC
Z80_instr_FD_35: ; DEC (IY+d)
+Z80_FETCH_VIA_IY_d
tax
dec
sta [PTR_DATA],z
bra Z80_common_DEC