| @@ -1,4 +1,4 @@ | |||||
| /* Copyright (C) 2014-2016 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| /* Copyright (C) 2014-2019 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| Released under the terms of the MIT License. See LICENSE for details. */ | Released under the terms of the MIT License. See LICENSE for details. */ | ||||
| #define POS(x) (!((x) & 0x80)) | #define POS(x) (!((x) & 0x80)) | ||||
| @@ -211,6 +211,15 @@ static inline void set_flags_scf(Z80 *z80) | |||||
| } | } | ||||
| /* | /* | ||||
| Set the flags for a LD A, I/R instruction. | |||||
| */ | |||||
| static inline void set_flags_ld_a_ir(Z80 *z80) | |||||
| { | |||||
| uint8_t val = z80->regs.a; | |||||
| set_flags(z80, 0, 0, z80->regs.iff2, F3(val), 0, F5(val), ZERO(val), SIGN(val), 0xFE); | |||||
| } | |||||
| /* | |||||
| Set the flags for a LDI/LDIR/LDD/LDDR instruction. | Set the flags for a LDI/LDIR/LDD/LDDR instruction. | ||||
| */ | */ | ||||
| static inline void set_flags_blockxfer(Z80 *z80, uint8_t val) | static inline void set_flags_blockxfer(Z80 *z80, uint8_t val) | ||||
| @@ -221,6 +230,19 @@ static inline void set_flags_blockxfer(Z80 *z80, uint8_t val) | |||||
| } | } | ||||
| /* | /* | ||||
| Set the flags for a CPI/CPIR/CPD/CPDR instruction. | |||||
| */ | |||||
| static inline void set_flags_blockcp(Z80 *z80, uint16_t rh) | |||||
| { | |||||
| uint8_t lh = z80->regs.a; | |||||
| bool pv = z80->regs.bc != 0; | |||||
| bool h = HALF(lh, -, rh); | |||||
| uint8_t res = lh - rh; | |||||
| uint8_t resh = res - h; | |||||
| set_flags(z80, 0, 1, pv, F3(resh), h, F5(resh), ZERO(res), SIGN(res), 0xFE); | |||||
| } | |||||
| /* | |||||
| Set the flags for an IN instruction. | Set the flags for an IN instruction. | ||||
| */ | */ | ||||
| static inline void set_flags_in(Z80 *z80, uint8_t val) | static inline void set_flags_in(Z80 *z80, uint8_t val) | ||||
| @@ -1,4 +1,4 @@ | |||||
| /* Copyright (C) 2014-2016 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| /* Copyright (C) 2014-2019 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| Released under the terms of the MIT License. See LICENSE for details. */ | Released under the terms of the MIT License. See LICENSE for details. */ | ||||
| /* | /* | ||||
| @@ -193,16 +193,28 @@ static uint8_t z80_inst_ld_nn_a(Z80 *z80, uint8_t opcode) | |||||
| /* | /* | ||||
| LD A, I (0xED57): | LD A, I (0xED57): | ||||
| Load I into A. | Load I into A. | ||||
| TODO | |||||
| */ | */ | ||||
| // static uint8_t z80_inst_ld_a_i(Z80 *z80, uint8_t opcode) | |||||
| static uint8_t z80_inst_ld_a_i(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| z80->regs.a = z80->regs.i; | |||||
| set_flags_ld_a_ir(z80); | |||||
| z80->regs.pc++; | |||||
| return 9; | |||||
| } | |||||
| /* | /* | ||||
| LD A, R (0xED5F): | LD A, R (0xED5F): | ||||
| Load R into A. | Load R into A. | ||||
| TODO | |||||
| */ | */ | ||||
| // static uint8_t z80_inst_ld_a_r(Z80 *z80, uint8_t opcode) | |||||
| static uint8_t z80_inst_ld_a_r(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| z80->regs.a = z80->regs.r; | |||||
| set_flags_ld_a_ir(z80); | |||||
| z80->regs.pc++; | |||||
| return 9; | |||||
| } | |||||
| /* | /* | ||||
| LD I, A (0xED47): | LD I, A (0xED47): | ||||
| @@ -536,13 +548,65 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode) | |||||
| return 21; | return 21; | ||||
| } | } | ||||
| // TODO: CPI | |||||
| /* | |||||
| CPI (0xEDA1): | |||||
| CP (HL); INC HL; DEC BL | |||||
| */ | |||||
| static uint8_t z80_inst_cpi(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
| z80->regs.hl++; | |||||
| z80->regs.bc--; | |||||
| set_flags_blockcp(z80, value); | |||||
| z80->regs.pc++; | |||||
| return 16; | |||||
| } | |||||
| /* | |||||
| CPIR (0xEDB1): | |||||
| CPI; JR PV; -2 | |||||
| */ | |||||
| static uint8_t z80_inst_cpir(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| z80_inst_cpi(z80, opcode); | |||||
| if (z80->regs.bc == 0) | |||||
| return 16; | |||||
| z80->regs.pc -= 2; | |||||
| return 21; | |||||
| } | |||||
| /* | |||||
| CPD (0xEDA9): | |||||
| CP (HL); DEC HL; DEC BL | |||||
| */ | |||||
| static uint8_t z80_inst_cpd(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
| // TODO: CPIR | |||||
| z80->regs.hl--; | |||||
| z80->regs.bc--; | |||||
| // TODO: CPD | |||||
| set_flags_blockcp(z80, value); | |||||
| z80->regs.pc++; | |||||
| return 16; | |||||
| } | |||||
| // TODO: CPDR | |||||
| /* | |||||
| CPDR (0xEDB9): | |||||
| CPD; JR PV; -2 | |||||
| */ | |||||
| static uint8_t z80_inst_cpdr(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| z80_inst_cpd(z80, opcode); | |||||
| if (z80->regs.bc == 0) | |||||
| return 16; | |||||
| z80->regs.pc -= 2; | |||||
| return 21; | |||||
| } | |||||
| /* | /* | ||||
| ADD A, r (0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87): | ADD A, r (0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87): | ||||
| @@ -1,4 +1,4 @@ | |||||
| /* Copyright (C) 2014-2016 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| /* Copyright (C) 2014-2019 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
| Released under the terms of the MIT License. See LICENSE for details. */ | Released under the terms of the MIT License. See LICENSE for details. */ | ||||
| static DispatchTable instruction_table = { | static DispatchTable instruction_table = { | ||||
| @@ -348,7 +348,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0x54] = z80_inst_neg, | [0x54] = z80_inst_neg, | ||||
| [0x55] = z80_inst_retn, | [0x55] = z80_inst_retn, | ||||
| [0x56] = z80_inst_im, | [0x56] = z80_inst_im, | ||||
| [0x57] = z80_inst_unimplemented, // TODO | |||||
| [0x57] = z80_inst_ld_a_i, | |||||
| [0x58] = z80_inst_in_r_c, | [0x58] = z80_inst_in_r_c, | ||||
| [0x59] = z80_inst_out_c_r, | [0x59] = z80_inst_out_c_r, | ||||
| [0x5A] = z80_inst_adc_hl_ss, | [0x5A] = z80_inst_adc_hl_ss, | ||||
| @@ -356,7 +356,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0x5C] = z80_inst_neg, | [0x5C] = z80_inst_neg, | ||||
| [0x5D] = z80_inst_retn, | [0x5D] = z80_inst_retn, | ||||
| [0x5E] = z80_inst_im, | [0x5E] = z80_inst_im, | ||||
| [0x5F] = z80_inst_unimplemented, // TODO | |||||
| [0x5F] = z80_inst_ld_a_r, | |||||
| [0x60] = z80_inst_in_r_c, | [0x60] = z80_inst_in_r_c, | ||||
| [0x61] = z80_inst_out_c_r, | [0x61] = z80_inst_out_c_r, | ||||
| [0x62] = z80_inst_sbc_hl_ss, | [0x62] = z80_inst_sbc_hl_ss, | ||||
| @@ -422,7 +422,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0x9E] = z80_inst_nop2, | [0x9E] = z80_inst_nop2, | ||||
| [0x9F] = z80_inst_nop2, | [0x9F] = z80_inst_nop2, | ||||
| [0xA0] = z80_inst_ldi, | [0xA0] = z80_inst_ldi, | ||||
| [0xA1] = z80_inst_unimplemented, // TODO | |||||
| [0xA1] = z80_inst_cpi, | |||||
| [0xA2] = z80_inst_ini, | [0xA2] = z80_inst_ini, | ||||
| [0xA3] = z80_inst_outi, | [0xA3] = z80_inst_outi, | ||||
| [0xA4] = z80_inst_nop2, | [0xA4] = z80_inst_nop2, | ||||
| @@ -430,7 +430,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0xA6] = z80_inst_nop2, | [0xA6] = z80_inst_nop2, | ||||
| [0xA7] = z80_inst_nop2, | [0xA7] = z80_inst_nop2, | ||||
| [0xA8] = z80_inst_ldd, | [0xA8] = z80_inst_ldd, | ||||
| [0xA9] = z80_inst_unimplemented, // TODO | |||||
| [0xA9] = z80_inst_cpd, | |||||
| [0xAA] = z80_inst_ind, | [0xAA] = z80_inst_ind, | ||||
| [0xAB] = z80_inst_outd, | [0xAB] = z80_inst_outd, | ||||
| [0xAC] = z80_inst_nop2, | [0xAC] = z80_inst_nop2, | ||||
| @@ -438,7 +438,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0xAE] = z80_inst_nop2, | [0xAE] = z80_inst_nop2, | ||||
| [0xAF] = z80_inst_nop2, | [0xAF] = z80_inst_nop2, | ||||
| [0xB0] = z80_inst_ldir, | [0xB0] = z80_inst_ldir, | ||||
| [0xB1] = z80_inst_unimplemented, // TODO | |||||
| [0xB1] = z80_inst_cpir, | |||||
| [0xB2] = z80_inst_inir, | [0xB2] = z80_inst_inir, | ||||
| [0xB3] = z80_inst_otir, | [0xB3] = z80_inst_otir, | ||||
| [0xB4] = z80_inst_nop2, | [0xB4] = z80_inst_nop2, | ||||
| @@ -446,7 +446,7 @@ static DispatchTable instruction_table_extended = { | |||||
| [0xB6] = z80_inst_nop2, | [0xB6] = z80_inst_nop2, | ||||
| [0xB7] = z80_inst_nop2, | [0xB7] = z80_inst_nop2, | ||||
| [0xB8] = z80_inst_lddr, | [0xB8] = z80_inst_lddr, | ||||
| [0xB9] = z80_inst_unimplemented, // TODO | |||||
| [0xB9] = z80_inst_cpdr, | |||||
| [0xBA] = z80_inst_indr, | [0xBA] = z80_inst_indr, | ||||
| [0xBB] = z80_inst_otdr, | [0xBB] = z80_inst_otdr, | ||||
| [0xBC] = z80_inst_nop2, | [0xBC] = z80_inst_nop2, | ||||