From 526c33f24b076ca74da9836685c01ba1eae58dc1 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sun, 1 Dec 2019 14:29:45 -0500 Subject: [PATCH] Implement LD A, I/R; CPI/CPIR/CPD/CPDR --- src/z80_flags.inc.c | 24 ++++++++++++++- src/z80_ops.inc.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++------ src/z80_tables.inc.c | 14 ++++----- 3 files changed, 103 insertions(+), 17 deletions(-) diff --git a/src/z80_flags.inc.c b/src/z80_flags.inc.c index fd6e3ae..1a2b5ac 100644 --- a/src/z80_flags.inc.c +++ b/src/z80_flags.inc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2016 Ben Kurtovic +/* Copyright (C) 2014-2019 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #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. */ 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. */ static inline void set_flags_in(Z80 *z80, uint8_t val) diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index 6976030..0055a5c 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2016 Ben Kurtovic +/* Copyright (C) 2014-2019 Ben Kurtovic 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): 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): 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): @@ -536,13 +548,65 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode) 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): diff --git a/src/z80_tables.inc.c b/src/z80_tables.inc.c index adc0520..fb89bca 100644 --- a/src/z80_tables.inc.c +++ b/src/z80_tables.inc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2016 Ben Kurtovic +/* Copyright (C) 2014-2019 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ static DispatchTable instruction_table = { @@ -348,7 +348,7 @@ static DispatchTable instruction_table_extended = { [0x54] = z80_inst_neg, [0x55] = z80_inst_retn, [0x56] = z80_inst_im, - [0x57] = z80_inst_unimplemented, // TODO + [0x57] = z80_inst_ld_a_i, [0x58] = z80_inst_in_r_c, [0x59] = z80_inst_out_c_r, [0x5A] = z80_inst_adc_hl_ss, @@ -356,7 +356,7 @@ static DispatchTable instruction_table_extended = { [0x5C] = z80_inst_neg, [0x5D] = z80_inst_retn, [0x5E] = z80_inst_im, - [0x5F] = z80_inst_unimplemented, // TODO + [0x5F] = z80_inst_ld_a_r, [0x60] = z80_inst_in_r_c, [0x61] = z80_inst_out_c_r, [0x62] = z80_inst_sbc_hl_ss, @@ -422,7 +422,7 @@ static DispatchTable instruction_table_extended = { [0x9E] = z80_inst_nop2, [0x9F] = z80_inst_nop2, [0xA0] = z80_inst_ldi, - [0xA1] = z80_inst_unimplemented, // TODO + [0xA1] = z80_inst_cpi, [0xA2] = z80_inst_ini, [0xA3] = z80_inst_outi, [0xA4] = z80_inst_nop2, @@ -430,7 +430,7 @@ static DispatchTable instruction_table_extended = { [0xA6] = z80_inst_nop2, [0xA7] = z80_inst_nop2, [0xA8] = z80_inst_ldd, - [0xA9] = z80_inst_unimplemented, // TODO + [0xA9] = z80_inst_cpd, [0xAA] = z80_inst_ind, [0xAB] = z80_inst_outd, [0xAC] = z80_inst_nop2, @@ -438,7 +438,7 @@ static DispatchTable instruction_table_extended = { [0xAE] = z80_inst_nop2, [0xAF] = z80_inst_nop2, [0xB0] = z80_inst_ldir, - [0xB1] = z80_inst_unimplemented, // TODO + [0xB1] = z80_inst_cpir, [0xB2] = z80_inst_inir, [0xB3] = z80_inst_otir, [0xB4] = z80_inst_nop2, @@ -446,7 +446,7 @@ static DispatchTable instruction_table_extended = { [0xB6] = z80_inst_nop2, [0xB7] = z80_inst_nop2, [0xB8] = z80_inst_lddr, - [0xB9] = z80_inst_unimplemented, // TODO + [0xB9] = z80_inst_cpdr, [0xBA] = z80_inst_indr, [0xBB] = z80_inst_otdr, [0xBC] = z80_inst_nop2,