From fdda540d263bdae252ff87daf86ebd327d874b15 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Fri, 29 Apr 2016 02:12:51 -0500 Subject: [PATCH] Refactor flag setting code; implement more instructions. --- src/vdp.c | 11 + src/z80.c | 17 +- src/z80_flags.inc.c | 100 +++++++++ src/z80_ops.inc.c | 612 +++++++++++++++++++++++++++++++++++++-------------- src/z80_tables.inc.c | 108 ++++----- 5 files changed, 619 insertions(+), 229 deletions(-) create mode 100644 src/z80_flags.inc.c diff --git a/src/vdp.c b/src/vdp.c index a8e5371..de6a978 100644 --- a/src/vdp.c +++ b/src/vdp.c @@ -266,4 +266,15 @@ void vdp_dump_registers(const VDP *vdp) DEBUG("- $08: 0x%02X (HS)", regs[0x08]) DEBUG("- $09: 0x%02X (VS)", regs[0x09]) DEBUG("- $0A: 0x%02X (LC)", regs[0x0A]) + + // TODO: remove me! + DEBUG("Dumping CRAM:") + for (uint8_t i = 0x00; i < 0x40; i += 0x10) { + uint16_t w[8]; + for (uint8_t j = 0; j < 8; j++) + w[j] = vdp->cram[i + j * 2] + (vdp->cram[i + j * 2 + 1] << 8); + + DEBUG("- %04X %04X %04X %04X %04X %04X %04X %04X", + w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]) + } } diff --git a/src/z80.c b/src/z80.c index e2c5f1b..5d551fa 100644 --- a/src/z80.c +++ b/src/z80.c @@ -90,10 +90,11 @@ static inline bool get_shadow_flag(const Z80 *z80, uint8_t flag) /* Update the F register flags according to the set bits in the mask. */ -static inline void update_flags(Z80 *z80, bool c, bool n, bool pv, bool f3, - bool h, bool f5, bool z, bool s, uint8_t mask) +static inline void set_flags(Z80 *z80, + bool c, bool n, bool pv, bool f3, bool h, bool f5, bool z, bool s, + uint8_t mask) { - z80->regs.f = (~mask & z80->regs.f) | (mask & ( + uint8_t new = ( c << FLAG_CARRY | n << FLAG_SUBTRACT | pv << FLAG_PARITY | @@ -101,9 +102,13 @@ static inline void update_flags(Z80 *z80, bool c, bool n, bool pv, bool f3, h << FLAG_HALFCARRY | f5 << FLAG_UNDOC_5 | z << FLAG_ZERO | - s << FLAG_SIGN)); + s << FLAG_SIGN + ); + z80->regs.f = (~mask & z80->regs.f) | (mask & new); } +#include "z80_flags.inc.c" + /* Push a two-byte value onto the stack. */ @@ -138,7 +143,7 @@ static void handle_io_errors(Z80 *z80) /* Read and return a byte from the given port, and check for errors. */ -static uint8_t read_port(Z80 *z80, uint8_t port) +static inline uint8_t read_port(Z80 *z80, uint8_t port) { uint8_t value = io_port_read(z80->io, port); handle_io_errors(z80); @@ -148,7 +153,7 @@ static uint8_t read_port(Z80 *z80, uint8_t port) /* Write a byte to the given port, and check for errors. */ -static void write_port(Z80 *z80, uint8_t port, uint8_t value) +static inline void write_port(Z80 *z80, uint8_t port, uint8_t value) { io_port_write(z80->io, port, value); handle_io_errors(z80); diff --git a/src/z80_flags.inc.c b/src/z80_flags.inc.c new file mode 100644 index 0000000..cde169e --- /dev/null +++ b/src/z80_flags.inc.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2014-2016 Ben Kurtovic + Released under the terms of the MIT License. See LICENSE for details. */ + +#define POS(x) (!((x) & 0x80)) +#define NEG(x) ((x) & 0x80) + +#define CARRY(lh, op, rh) (((lh) op (rh)) & 0x100) +#define HALF(lh, op, rh) ((((lh) & 0x0F) op ((rh) & 0x0F)) & 0x10) +#define ZERO(x) ((x) == 0) +#define SIGN(x) NEG(x) +#define SUB 1 + +#define OV_ADD(lh, rh, res) \ + (POS(lh) && POS(rh) && NEG(res) || NEG(lh) && NEG(rh) && POS(res)) +#define OV_SUB(lh, rh, res) \ + (POS(lh) && NEG(rh) && NEG(res) || NEG(lh) && POS(rh) && POS(res)) + +#define PARITY(x) (!(__builtin_popcount(x) % 2)) + +#define F3(x) ((x) & 0x08) +#define F5(x) ((x) & 0x20) + +/* + Set the flags for an 8-bit ADD or ADC instruction. +*/ +static inline void set_flags_add8(Z80 *z80, uint16_t rh) +{ + uint8_t lh = z80->regs.a; + uint8_t res = lh + rh; + set_flags(z80, CARRY(lh, +, rh), !SUB, OV_ADD(lh, rh, res), F3(res), + HALF(lh, +, rh), F5(res), ZERO(res), SIGN(res), 0xFF); +} + +/* + Set the flags for an 8-bit SUB or SBC instruction. +*/ +static inline void set_flags_sub8(Z80 *z80, uint16_t rh) +{ + uint8_t lh = z80->regs.a; + uint8_t res = lh - rh; + set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(res), + HALF(lh, -, rh), F5(res), ZERO(res), SIGN(res), 0xFF); +} + +/* + Set the flags for a CP instruction. +*/ +static inline void set_flags_cp(Z80 *z80, uint16_t rh) +{ + uint8_t lh = z80->regs.a; + uint8_t res = lh - rh; + set_flags(z80, CARRY(lh, -, rh), SUB, OV_SUB(lh, rh, res), F3(rh), + HALF(lh, -, rh), F5(rh), ZERO(res), SIGN(res), 0xFF); +} + +/* + Set the flags for an AND, XOR, or OR instruction. +*/ +static inline void set_flags_bitwise(Z80 *z80, uint8_t res, bool is_and) +{ + set_flags(z80, 0, 0, PARITY(res), F3(res), is_and, F5(res), ZERO(res), + SIGN(res), 0xFF); +} + +/* + Set the flags for an 8-bit INC instruction. +*/ +static inline void set_flags_inc(Z80 *z80, uint8_t val) +{ + uint8_t res = val + 1; + set_flags(z80, 0, !SUB, OV_ADD(val, 1, res), F3(res), HALF(val, +, 1), + F5(res), ZERO(res), SIGN(res), 0xFE); +} + +/* + Set the flags for an 8-bit DEC instruction. +*/ +static inline void set_flags_dec(Z80 *z80, uint8_t val) +{ + uint8_t res = val - 1; + set_flags(z80, 0, SUB, OV_SUB(val, 1, res), F3(res), HALF(val, -, 1), + F5(res), ZERO(res), SIGN(res), 0xFE); +} + +// set_flags(Z80 *z80, +// bool c, bool n, bool pv, bool f3, bool h, bool f5, bool z, bool s, +// uint8_t mask) + +#undef POS +#undef NEG +#undef CARRY +#undef HALF +#undef ZERO +#undef SIGN +#undef SUB +#undef OV_ADD +#undef OV_SUB +#undef PARITY +#undef F3 +#undef F5 diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index ffc74bb..14c23b0 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -484,7 +484,7 @@ static uint8_t z80_inst_ldi(Z80 *z80, uint8_t opcode) z80->regs.de++; z80->regs.bc--; - update_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16); + set_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16); z80->regs.pc++; return 16; } @@ -516,7 +516,7 @@ static uint8_t z80_inst_ldd(Z80 *z80, uint8_t opcode) z80->regs.de--; z80->regs.bc--; - update_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16); + set_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16); z80->regs.pc++; return 16; } @@ -534,31 +534,151 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode) return 21; } -// CPI +// TODO; CPI -// CPIR +// TODO: CPIR -// CPD +// TODO: CPD -// CPDR +// TODO: CPDR -// ADD A, r +/* + ADD A, r (0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87): + TODO +*/ +static uint8_t z80_inst_add_a_r(Z80 *z80, uint8_t opcode) +{ + uint8_t value = *extract_reg(z80, opcode << 3); -// ADD A, n + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 4; +} -// ADD A, (HL) +/* + ADD A, n (0xC6): + TODO +*/ +static uint8_t z80_inst_add_a_n(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); -// ADD A, (IXY+d) + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 7; +} -// ADC A, r +/* + ADD A, (HL) (0x86): + TODO +*/ +static uint8_t z80_inst_add_a_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); -// ADC A, n + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 7; +} -// ADC A, (HL) +/* + ADD A, (IXY+d) (0xDD86, 0xFD86): + TODO +*/ +static uint8_t z80_inst_add_a_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); -// ADC A, (IXY+d) + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 19; +} + +/* + ADC A, r (0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8F): + TODO +*/ +static uint8_t z80_inst_adc_a_r(Z80 *z80, uint8_t opcode) +{ + uint16_t value = *extract_reg(z80, opcode << 3); + value += get_flag(z80, FLAG_CARRY); + + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 4; +} + +/* + ADC A, n (0xCE): + TODO +*/ +static uint8_t z80_inst_adc_a_n(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + value += get_flag(z80, FLAG_CARRY); -// SUB r + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 7; +} + +/* + ADC A, (HL) (0x8E): + TODO +*/ +static uint8_t z80_inst_adc_a_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + value += get_flag(z80, FLAG_CARRY); + + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 7; +} + +/* + ADC A, (IXY+d) (0xDD8E, 0xFD8E): + TODO +*/ +static uint8_t z80_inst_adc_a_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint16_t value = mmu_read_byte(z80->mmu, addr); + value += get_flag(z80, FLAG_CARRY); + + set_flags_add8(z80, value); + z80->regs.a += value; + z80->regs.pc++; + return 19; +} + +/* + SUB, r (0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97): + TODO +*/ +static uint8_t z80_inst_sub_r(Z80 *z80, uint8_t opcode) +{ + uint8_t value = *extract_reg(z80, opcode << 3); + + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 4; +} /* SUB n (0xD6): @@ -567,33 +687,122 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_sub_n(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t imm = mmu_read_byte(z80->mmu, ++z80->regs.pc); - uint8_t orig = z80->regs.a; - uint8_t a = z80->regs.a -= imm; + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); - bool c = (orig - imm) != a; - bool v = (orig - imm) != ((int8_t) a); - bool h = !!(((orig & 0x0F) - (imm & 0x0F)) & 0x10); - update_flags(z80, c, 1, v, !!(a & 0x08), h, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 7; +} +/* + SUB (HL) + TODO +*/ +static uint8_t z80_inst_sub_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + + set_flags_sub8(z80, value); + z80->regs.a -= value; z80->regs.pc++; return 7; } -// SUB (HL) +/* + SUB (IXY+d) + TODO +*/ +static uint8_t z80_inst_sub_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); -// SUB (IXY+d) + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 19; +} -// SBC A, r +/* + SBC A, r (...): + TODO +*/ +static uint8_t z80_inst_sbc_a_r(Z80 *z80, uint8_t opcode) +{ + uint8_t value = *extract_reg(z80, opcode << 3); + value += get_flag(z80, FLAG_CARRY); -// SBC A, n + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 4; +} -// SBC A, (HL) +/* + SBC A, n (...): + TODO +*/ +static uint8_t z80_inst_sbc_a_n(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + value += get_flag(z80, FLAG_CARRY); -// SBC A, (IXY+d) + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 7; +} -// AND r +/* + SBC A, (HL) + TODO +*/ +static uint8_t z80_inst_sbc_a_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + value += get_flag(z80, FLAG_CARRY); + + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 7; +} + +/* + SBC A, (IXY+d) + TODO +*/ +static uint8_t z80_inst_sbc_a_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); + value += get_flag(z80, FLAG_CARRY); + + set_flags_sub8(z80, value); + z80->regs.a -= value; + z80->regs.pc++; + return 19; +} + +/* + AND r + TODO +*/ +static uint8_t z80_inst_and_r(Z80 *z80, uint8_t opcode) +{ + uint8_t value = *extract_reg(z80, opcode << 3); + uint8_t res = z80->regs.a &= value; + + set_flags_bitwise(z80, res, true); + z80->regs.pc++; + return 4; +} /* AND n (0xE6): @@ -602,20 +811,44 @@ static uint8_t z80_inst_sub_n(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_and_n(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t imm = mmu_read_byte(z80->mmu, ++z80->regs.pc); - uint8_t a = (z80->regs.a &= imm); + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + uint8_t res = z80->regs.a &= value; - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 1, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + set_flags_bitwise(z80, res, true); + z80->regs.pc++; + return 7; +} + +/* + AND (HL) + TODO +*/ +static uint8_t z80_inst_and_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + uint8_t res = z80->regs.a &= value; + set_flags_bitwise(z80, res, true); z80->regs.pc++; return 7; } -// AND (HL) +/* + AND (IXY+d) + TODO +*/ +static uint8_t z80_inst_and_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); + uint8_t res = z80->regs.a &= value; -// AND (IXY+d) + set_flags_bitwise(z80, res, true); + z80->regs.pc++; + return 19; +} /* OR r (0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB7): @@ -623,13 +856,10 @@ static uint8_t z80_inst_and_n(Z80 *z80, uint8_t opcode) */ static uint8_t z80_inst_or_r(Z80 *z80, uint8_t opcode) { - uint8_t *reg = extract_reg(z80, opcode << 3); - uint8_t a = (z80->regs.a |= *reg); - - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 0, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + uint8_t value = *extract_reg(z80, opcode << 3); + uint8_t res = z80->regs.a |= value; + set_flags_bitwise(z80, res, false); z80->regs.pc++; return 4; } @@ -641,18 +871,28 @@ static uint8_t z80_inst_or_r(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_or_n(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t imm = mmu_read_byte(z80->mmu, ++z80->regs.pc); - uint8_t a = (z80->regs.a |= imm); - - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 0, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + uint8_t res = z80->regs.a |= value; + set_flags_bitwise(z80, res, false); z80->regs.pc++; return 7; } -// OR (HL) +/* + OR (HL) + TODO +*/ +static uint8_t z80_inst_or_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + uint8_t res = z80->regs.a |= value; + + set_flags_bitwise(z80, res, false); + z80->regs.pc++; + return 7; +} /* OR (IXY+d) (0xDDB6, 0xFDB6): @@ -661,16 +901,13 @@ static uint8_t z80_inst_or_n(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_or_ixy(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t addr = get_index_addr(z80, ++z80->regs.pc); - uint8_t val = mmu_read_byte(z80->mmu, addr); - uint8_t a = (z80->regs.a |= val); - - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 0, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); + uint8_t res = z80->regs.a |= value; + set_flags_bitwise(z80, res, false); z80->regs.pc++; - return 7; + return 19; } /* @@ -679,13 +916,10 @@ static uint8_t z80_inst_or_ixy(Z80 *z80, uint8_t opcode) */ static uint8_t z80_inst_xor_r(Z80 *z80, uint8_t opcode) { - uint8_t *reg = extract_reg(z80, opcode << 3); - uint8_t a = (z80->regs.a ^= *reg); - - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 0, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + uint8_t value = *extract_reg(z80, opcode << 3); + uint8_t res = z80->regs.a ^= value; + set_flags_bitwise(z80, res, false); z80->regs.pc++; return 4; } @@ -697,20 +931,43 @@ static uint8_t z80_inst_xor_r(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_xor_n(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t imm = mmu_read_byte(z80->mmu, ++z80->regs.pc); - uint8_t a = (z80->regs.a ^= imm); - - bool parity = !(__builtin_popcount(a) % 2); - update_flags(z80, 0, 0, parity, !!(a & 0x08), 0, !!(a & 0x20), a == 0, - !!(a & 0x80), 0xFF); + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + uint8_t res = z80->regs.a ^= value; + set_flags_bitwise(z80, res, false); z80->regs.pc++; return 7; } -// XOR (HL) +/* + XOR (HL) + TODO +*/ +static uint8_t z80_inst_xor_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + uint8_t res = z80->regs.a ^= value; + + set_flags_bitwise(z80, res, false); + z80->regs.pc++; + return 7; +} +/* + XOR (IXY+d) + TODO +*/ +static uint8_t z80_inst_xor_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); + uint8_t res = z80->regs.a ^= value; -// XOR (IXY+d) + set_flags_bitwise(z80, res, false); + z80->regs.pc++; + return 19; +} /* CP r (0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBF): @@ -718,15 +975,9 @@ static uint8_t z80_inst_xor_n(Z80 *z80, uint8_t opcode) */ static uint8_t z80_inst_cp_r(Z80 *z80, uint8_t opcode) { - uint8_t *reg = extract_reg(z80, opcode << 3); - uint8_t d = z80->regs.a - *reg; - - bool c = (z80->regs.a - *reg) != d; - bool v = (z80->regs.a - *reg) != ((int8_t) d); - bool h = !!(((z80->regs.a & 0x0F) - (*reg & 0x0F)) & 0x10); - update_flags(z80, c, 1, v, !!(*reg & 0x08), h, !!(*reg & 0x20), d == 0, - !!(d & 0x80), 0xFF); + uint8_t value = *extract_reg(z80, opcode << 3); + set_flags_cp(z80, value); z80->regs.pc++; return 4; } @@ -738,15 +989,9 @@ static uint8_t z80_inst_cp_r(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_cp_n(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t n = mmu_read_byte(z80->mmu, ++z80->regs.pc); - uint8_t d = z80->regs.a - n; - - bool c = (z80->regs.a - n) != d; - bool v = (z80->regs.a - n) != ((int8_t) d); - bool h = !!(((z80->regs.a & 0x0F) - (n & 0x0F)) & 0x10); - update_flags(z80, c, 1, v, !!(n & 0x08), h, !!(n & 0x20), d == 0, - !!(d & 0x80), 0xFF); + uint8_t value = mmu_read_byte(z80->mmu, ++z80->regs.pc); + set_flags_cp(z80, value); z80->regs.pc++; return 7; } @@ -758,20 +1003,27 @@ static uint8_t z80_inst_cp_n(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_cp_hl(Z80 *z80, uint8_t opcode) { (void) opcode; - uint8_t n = mmu_read_byte(z80->mmu, z80->regs.hl); - uint8_t d = z80->regs.a - n; - - bool c = (z80->regs.a - n) != d; - bool v = (z80->regs.a - n) != ((int8_t) d); - bool h = !!(((z80->regs.a & 0x0F) - (n & 0x0F)) & 0x10); - update_flags(z80, c, 1, v, !!(n & 0x08), h, !!(n & 0x20), d == 0, - !!(d & 0x80), 0xFF); + uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl); + set_flags_cp(z80, value); z80->regs.pc++; return 7; } -// CP (IXY+d) +/* + CP (IXY+d) + TODO +*/ +static uint8_t z80_inst_cp_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t value = mmu_read_byte(z80->mmu, addr); + + set_flags_cp(z80, value); + z80->regs.pc++; + return 19; +} /* INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C): @@ -780,11 +1032,9 @@ static uint8_t z80_inst_cp_hl(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_inc_r(Z80 *z80, uint8_t opcode) { uint8_t *reg = extract_reg(z80, opcode); - bool halfcarry = !!(((*reg & 0x0F) + 1) & 0x10); - (*reg)++; - update_flags(z80, 0, 0, *reg == 0x80, !!(*reg & 0x08), halfcarry, - !!(*reg & 0x20), *reg == 0, !!(*reg & 0x80), 0xFE); + set_flags_inc(z80, *reg); + (*reg)++; z80->regs.pc++; return 4; } @@ -797,16 +1047,28 @@ static uint8_t z80_inst_inc_hl(Z80 *z80, uint8_t opcode) { (void) opcode; uint8_t byte = mmu_read_byte(z80->mmu, z80->regs.hl); - bool halfcarry = !!(((byte & 0x0F) + 1) & 0x10); - mmu_write_byte(z80->mmu, z80->regs.hl, ++byte); - update_flags(z80, 0, 0, byte == 0x80, !!(byte & 0x08), halfcarry, - !!(byte & 0x20), byte == 0, !!(byte & 0x80), 0xFE); + set_flags_inc(z80, byte); + mmu_write_byte(z80->mmu, z80->regs.hl, ++byte); z80->regs.pc++; return 11; } -// INC (IXY+d) +/* + INC (IXY+d) + TODO +*/ +static uint8_t z80_inst_inc_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t byte = mmu_read_byte(z80->mmu, addr); + + set_flags_inc(z80, byte); + mmu_write_byte(z80->mmu, addr, ++byte); + z80->regs.pc++; + return 23; +} /* DEC r (0x05, 0x0D, 0x15, 0x1D, 0x25, 0x2D, 0x3D): @@ -815,11 +1077,9 @@ static uint8_t z80_inst_inc_hl(Z80 *z80, uint8_t opcode) static uint8_t z80_inst_dec_r(Z80 *z80, uint8_t opcode) { uint8_t *reg = extract_reg(z80, opcode); - bool halfcarry = !!(((*reg & 0x0F) - 1) & 0x10); - (*reg)--; - update_flags(z80, 0, 1, *reg == 0x7F, !!(*reg & 0x08), halfcarry, - !!(*reg & 0x20), *reg == 0, !!(*reg & 0x80), 0xFE); + set_flags_dec(z80, *reg); + (*reg)--; z80->regs.pc++; return 4; } @@ -832,26 +1092,40 @@ static uint8_t z80_inst_dec_hl(Z80 *z80, uint8_t opcode) { (void) opcode; uint8_t byte = mmu_read_byte(z80->mmu, z80->regs.hl); - bool halfcarry = !!(((byte & 0x0F) + 1) & 0x10); - mmu_write_byte(z80->mmu, z80->regs.hl, --byte); - update_flags(z80, 0, 1, byte == 0x7F, !!(byte & 0x08), halfcarry, - !!(byte & 0x20), byte == 0, !!(byte & 0x80), 0xFE); + set_flags_dec(z80, byte); + mmu_write_byte(z80->mmu, z80->regs.hl, --byte); z80->regs.pc++; return 11; } -// DEC (IXY+d) +/* + DEC (IXY+d) + TODO +*/ +static uint8_t z80_inst_dec_ixy(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_index_addr(z80, ++z80->regs.pc); + uint8_t byte = mmu_read_byte(z80->mmu, addr); + + set_flags_dec(z80, byte); + mmu_write_byte(z80->mmu, addr, --byte); + z80->regs.pc++; + return 23; +} + +// ---------------------------------------------------------------------------- -// DAA +// TODO: DAA -// CPL +// TODO: CPL -// NEG +// TODO: NEG -// CCF +// TODO: CCF -// SCF +// TODO: SCF /* NOP (0x00): @@ -942,14 +1216,14 @@ static uint8_t z80_inst_add_hl_ss(Z80 *z80, uint8_t opcode) z80->regs.hl = value; bool h = !!(((lh & 0x0FFF) + (rh & 0x0FFF)) & 0x1000); - update_flags(z80, (lh + rh) != value, 0, 0, !!(value & 0x0800), h, + set_flags(z80, (lh + rh) != value, 0, 0, !!(value & 0x0800), h, !!(value & 0x2000), 0, 0, 0x3B); z80->regs.pc++; return 11; } -// ADC HL, ss +// TODO: ADC HL, ss /* SBC HL, ss (0xED42, 0xED52, 0xED62, 0xED72): @@ -966,14 +1240,14 @@ static uint8_t z80_inst_sbc_hl_ss(Z80 *z80, uint8_t opcode) bool ov = (minu - subtra) != ((int16_t) value); bool hc = !!(((minu & 0x0FFF) - (subtra & 0x0FFF)) & 0x1000); - update_flags(z80, c, 1, ov, !!(value & 0x0800), hc, + set_flags(z80, c, 1, ov, !!(value & 0x0800), hc, !!(value & 0x2000), value == 0, !!(value & 0x8000), 0xFF); z80->regs.pc++; return 15; } -// ADD IXY, pp +// TODO: ADD IXY, pp /* INC ss (0x03, 0x13, 0x23, 0x33): @@ -986,7 +1260,7 @@ static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t opcode) return 6; } -// INC IXY +// TODO: INC IXY /* DEC ss (0x0B, 0x1B, 0x2B, 0x3B): @@ -999,61 +1273,61 @@ static uint8_t z80_inst_dec_ss(Z80 *z80, uint8_t opcode) return 6; } -// DEC IXY +// TODO: DEC IXY -// RLCA +// TODO: RLCA -// RLA +// TODO: RLA -// RRCA +// TODO: RRCA -// RRA +// TODO: RRA -// RLC r +// TODO: RLC r -// RLC (HL) +// TODO: RLC (HL) -// RLC (IXY+d) +// TODO: RLC (IXY+d) -// RL r +// TODO: RL r -// RL (HL) +// TODO: RL (HL) -// RL (IXY+d) +// TODO: RL (IXY+d) -// RRC r +// TODO: RRC r -// RRC (HL) +// TODO: RRC (HL) -// RRC (IXY+d) +// TODO: RRC (IXY+d) -// RR r +// TODO: RR r -// RR (HL) +// TODO: RR (HL) -// RR (IXY+d) +// TODO: RR (IXY+d) -// SLA r +// TODO: SLA r -// SLA (HL) +// TODO: SLA (HL) -// SLA (IXY+d) +// TODO: SLA (IXY+d) -// SRA r +// TODO: SRA r -// SRA (HL) +// TODO: SRA (HL) -// SRA (IXY+d) +// TODO: SRA (IXY+d) -// SRL r +// TODO: SRL r -// SRL (HL) +// TODO: SRL (HL) -// SRL (IXY+d) +// TODO: SRL (IXY+d) -// RLD +// TODO: RLD -// RRD +// TODO: RRD /* BIT b, r (0xCB40, 0xCB41, 0xCB42, 0xCB43, 0xCB44, 0xCB45, 0xCB47, 0xCB48, @@ -1071,9 +1345,9 @@ static uint8_t z80_inst_bit_b_r(Z80 *z80, uint8_t opcode) uint8_t bit = (opcode >> 3) & 0x07; bool z = (((*reg) >> bit) & 1) == 0; if (z) - update_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); + set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); else - update_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); + set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); z80->regs.pc++; return 8; } @@ -1089,9 +1363,9 @@ static uint8_t z80_inst_bit_b_hl(Z80 *z80, uint8_t opcode) uint8_t bit = (opcode >> 3) & 0x07; bool z = ((val >> bit) & 1) == 0; if (z) - update_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); + set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); else - update_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); + set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); z80->regs.pc++; return 8; } @@ -1107,20 +1381,20 @@ static uint8_t z80_inst_bit_b_ixy(Z80 *z80, uint8_t opcode) uint8_t bit = (opcode >> 3) & 0x07; bool z = ((val >> bit) & 1) == 0; if (z) - update_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); + set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); else - update_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); + set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); z80->regs.pc++; return 8; } -// SET b, r +// TODO: SET b, r -// SET b, (HL) +// TODO: SET b, (HL) -// SET b, (IXY+d) +// TODO: SET b, (IXY+d) -// RES b, r +// TODO: RES b, r /* RES b, (HL) (0xCB86, 0xCB8E, 0xCB96, 0xCB9E, 0xCBA6, 0xCBAE, 0xCBB6, @@ -1137,7 +1411,7 @@ static uint8_t z80_inst_res_b_hl(Z80 *z80, uint8_t opcode) return 8; } -// RES b, (IXY+d) +// TODO: RES b, (IXY+d) /* JP nn (0xC3): @@ -1344,7 +1618,7 @@ static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode) if (opcode != 0x70) *extract_reg(z80, opcode) = data; - update_flags(z80, 0, 0, parity, !!(data & 0x08), 0, !!(data & 0x20), + set_flags(z80, 0, 0, parity, !!(data & 0x08), 0, !!(data & 0x20), data == 0, !!(data & 0x80), 0xFE); z80->regs.pc++; return 12; @@ -1364,7 +1638,7 @@ static uint8_t z80_inst_ini(Z80 *z80, uint8_t opcode) z80->regs.hl++; (*b)--; - update_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), + set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), *b == 0, !!(*b & 0x80), 0xFE); z80->regs.pc++; return 16; @@ -1397,7 +1671,7 @@ static uint8_t z80_inst_ind(Z80 *z80, uint8_t opcode) z80->regs.hl--; (*b)--; - update_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), + set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), *b == 0, !!(*b & 0x80), 0xFE); z80->regs.pc++; return 16; @@ -1456,7 +1730,7 @@ static uint8_t z80_inst_outi(Z80 *z80, uint8_t opcode) z80->regs.hl++; (*b)--; - update_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), + set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), *b == 0, !!(*b & 0x80), 0xFE); z80->regs.pc++; return 16; @@ -1489,7 +1763,7 @@ static uint8_t z80_inst_outd(Z80 *z80, uint8_t opcode) z80->regs.hl--; (*b)--; - update_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), + set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20), *b == 0, !!(*b & 0x80), 0xFE); z80->regs.pc++; return 16; diff --git a/src/z80_tables.inc.c b/src/z80_tables.inc.c index f669722..5add7c5 100644 --- a/src/z80_tables.inc.c +++ b/src/z80_tables.inc.c @@ -130,53 +130,53 @@ static DispatchTable instruction_table = { [0x7D] = z80_inst_ld_r_r, [0x7E] = z80_inst_ld_r_hl, [0x7F] = z80_inst_ld_r_r, - [0x80] = z80_inst_unimplemented, // TODO - [0x81] = z80_inst_unimplemented, // TODO - [0x82] = z80_inst_unimplemented, // TODO - [0x83] = z80_inst_unimplemented, // TODO - [0x84] = z80_inst_unimplemented, // TODO - [0x85] = z80_inst_unimplemented, // TODO - [0x86] = z80_inst_unimplemented, // TODO - [0x87] = z80_inst_unimplemented, // TODO - [0x88] = z80_inst_unimplemented, // TODO - [0x89] = z80_inst_unimplemented, // TODO - [0x8A] = z80_inst_unimplemented, // TODO - [0x8B] = z80_inst_unimplemented, // TODO - [0x8C] = z80_inst_unimplemented, // TODO - [0x8D] = z80_inst_unimplemented, // TODO - [0x8E] = z80_inst_unimplemented, // TODO - [0x8F] = z80_inst_unimplemented, // TODO - [0x90] = z80_inst_unimplemented, // TODO - [0x91] = z80_inst_unimplemented, // TODO - [0x92] = z80_inst_unimplemented, // TODO - [0x93] = z80_inst_unimplemented, // TODO - [0x94] = z80_inst_unimplemented, // TODO - [0x95] = z80_inst_unimplemented, // TODO - [0x96] = z80_inst_unimplemented, // TODO - [0x97] = z80_inst_unimplemented, // TODO - [0x98] = z80_inst_unimplemented, // TODO - [0x99] = z80_inst_unimplemented, // TODO - [0x9A] = z80_inst_unimplemented, // TODO - [0x9B] = z80_inst_unimplemented, // TODO - [0x9C] = z80_inst_unimplemented, // TODO - [0x9D] = z80_inst_unimplemented, // TODO - [0x9E] = z80_inst_unimplemented, // TODO - [0x9F] = z80_inst_unimplemented, // TODO - [0xA0] = z80_inst_unimplemented, // TODO - [0xA1] = z80_inst_unimplemented, // TODO - [0xA2] = z80_inst_unimplemented, // TODO - [0xA3] = z80_inst_unimplemented, // TODO - [0xA4] = z80_inst_unimplemented, // TODO - [0xA5] = z80_inst_unimplemented, // TODO - [0xA6] = z80_inst_unimplemented, // TODO - [0xA7] = z80_inst_unimplemented, // TODO + [0x80] = z80_inst_add_a_r, + [0x81] = z80_inst_add_a_r, + [0x82] = z80_inst_add_a_r, + [0x83] = z80_inst_add_a_r, + [0x84] = z80_inst_add_a_r, + [0x85] = z80_inst_add_a_r, + [0x86] = z80_inst_add_a_hl, + [0x87] = z80_inst_add_a_r, + [0x88] = z80_inst_adc_a_r, + [0x89] = z80_inst_adc_a_r, + [0x8A] = z80_inst_adc_a_r, + [0x8B] = z80_inst_adc_a_r, + [0x8C] = z80_inst_adc_a_r, + [0x8D] = z80_inst_adc_a_r, + [0x8E] = z80_inst_adc_a_hl, + [0x8F] = z80_inst_adc_a_r, + [0x90] = z80_inst_sub_r, + [0x91] = z80_inst_sub_r, + [0x92] = z80_inst_sub_r, + [0x93] = z80_inst_sub_r, + [0x94] = z80_inst_sub_r, + [0x95] = z80_inst_sub_r, + [0x96] = z80_inst_sub_hl, + [0x97] = z80_inst_sub_r, + [0x98] = z80_inst_sbc_a_r, + [0x99] = z80_inst_sbc_a_r, + [0x9A] = z80_inst_sbc_a_r, + [0x9B] = z80_inst_sbc_a_r, + [0x9C] = z80_inst_sbc_a_r, + [0x9D] = z80_inst_sbc_a_r, + [0x9E] = z80_inst_sbc_a_hl, + [0x9F] = z80_inst_sbc_a_r, + [0xA0] = z80_inst_and_r, + [0xA1] = z80_inst_and_r, + [0xA2] = z80_inst_and_r, + [0xA3] = z80_inst_and_r, + [0xA4] = z80_inst_and_r, + [0xA5] = z80_inst_and_r, + [0xA6] = z80_inst_and_hl, + [0xA7] = z80_inst_and_r, [0xA8] = z80_inst_xor_r, [0xA9] = z80_inst_xor_r, [0xAA] = z80_inst_xor_r, [0xAB] = z80_inst_xor_r, [0xAC] = z80_inst_xor_r, [0xAD] = z80_inst_xor_r, - [0xAE] = z80_inst_unimplemented, // TODO + [0xAE] = z80_inst_xor_hl, [0xAF] = z80_inst_xor_r, [0xB0] = z80_inst_or_r, [0xB1] = z80_inst_or_r, @@ -184,7 +184,7 @@ static DispatchTable instruction_table = { [0xB3] = z80_inst_or_r, [0xB4] = z80_inst_or_r, [0xB5] = z80_inst_or_r, - [0xB6] = z80_inst_unimplemented, // TODO + [0xB6] = z80_inst_or_hl, [0xB7] = z80_inst_or_r, [0xB8] = z80_inst_cp_r, [0xB9] = z80_inst_cp_r, @@ -200,7 +200,7 @@ static DispatchTable instruction_table = { [0xC3] = z80_inst_jp_nn, [0xC4] = z80_inst_call_cc_nn, [0xC5] = z80_inst_push_qq, - [0xC6] = z80_inst_unimplemented, // TODO + [0xC6] = z80_inst_add_a_n, [0xC7] = z80_inst_rst_p, [0xC8] = z80_inst_ret_cc, [0xC9] = z80_inst_ret, @@ -208,7 +208,7 @@ static DispatchTable instruction_table = { [0xCB] = z80_prefix_bits, [0xCC] = z80_inst_call_cc_nn, [0xCD] = z80_inst_call_nn, - [0xCE] = z80_inst_unimplemented, // TODO + [0xCE] = z80_inst_adc_a_n, [0xCF] = z80_inst_rst_p, [0xD0] = z80_inst_ret_cc, [0xD1] = z80_inst_pop_qq, @@ -224,7 +224,7 @@ static DispatchTable instruction_table = { [0xDB] = z80_inst_in_a_n, [0xDC] = z80_inst_call_cc_nn, [0xDD] = z80_prefix_index, - [0xDE] = z80_inst_unimplemented, // TODO + [0xDE] = z80_inst_sbc_a_n, [0xDF] = z80_inst_rst_p, [0xE0] = z80_inst_ret_cc, [0xE1] = z80_inst_pop_qq, @@ -831,8 +831,8 @@ static DispatchTable instruction_table_index = { [0x31] = z80_inst_nop2, [0x32] = z80_inst_nop2, [0x33] = z80_inst_nop2, - [0x34] = z80_inst_unimplemented, // TODO - [0x35] = z80_inst_unimplemented, // TODO + [0x34] = z80_inst_inc_ixy, + [0x35] = z80_inst_dec_ixy, [0x36] = z80_inst_ld_ixy_n, [0x37] = z80_inst_nop2, [0x38] = z80_inst_nop2, @@ -913,7 +913,7 @@ static DispatchTable instruction_table_index = { [0x83] = z80_inst_nop2, [0x84] = z80_inst_unimplemented, // TODO [0x85] = z80_inst_unimplemented, // TODO - [0x86] = z80_inst_unimplemented, // TODO + [0x86] = z80_inst_add_a_ixy, [0x87] = z80_inst_nop2, [0x88] = z80_inst_nop2, [0x89] = z80_inst_nop2, @@ -921,7 +921,7 @@ static DispatchTable instruction_table_index = { [0x8B] = z80_inst_nop2, [0x8C] = z80_inst_unimplemented, // TODO [0x8D] = z80_inst_unimplemented, // TODO - [0x8E] = z80_inst_unimplemented, // TODO + [0x8E] = z80_inst_adc_a_ixy, [0x8F] = z80_inst_nop2, [0x90] = z80_inst_nop2, [0x91] = z80_inst_nop2, @@ -929,7 +929,7 @@ static DispatchTable instruction_table_index = { [0x93] = z80_inst_nop2, [0x94] = z80_inst_unimplemented, // TODO [0x95] = z80_inst_unimplemented, // TODO - [0x96] = z80_inst_unimplemented, // TODO + [0x96] = z80_inst_sub_ixy, [0x97] = z80_inst_nop2, [0x98] = z80_inst_nop2, [0x99] = z80_inst_nop2, @@ -937,7 +937,7 @@ static DispatchTable instruction_table_index = { [0x9B] = z80_inst_nop2, [0x9C] = z80_inst_unimplemented, // TODO [0x9D] = z80_inst_unimplemented, // TODO - [0x9E] = z80_inst_unimplemented, // TODO + [0x9E] = z80_inst_sbc_a_ixy, [0x9F] = z80_inst_nop2, [0xA0] = z80_inst_nop2, [0xA1] = z80_inst_nop2, @@ -945,7 +945,7 @@ static DispatchTable instruction_table_index = { [0xA3] = z80_inst_nop2, [0xA4] = z80_inst_unimplemented, // TODO [0xA5] = z80_inst_unimplemented, // TODO - [0xA6] = z80_inst_unimplemented, // TODO + [0xA6] = z80_inst_and_ixy, [0xA7] = z80_inst_nop2, [0xA8] = z80_inst_nop2, [0xA9] = z80_inst_nop2, @@ -953,7 +953,7 @@ static DispatchTable instruction_table_index = { [0xAB] = z80_inst_nop2, [0xAC] = z80_inst_unimplemented, // TODO [0xAD] = z80_inst_unimplemented, // TODO - [0xAE] = z80_inst_unimplemented, // TODO + [0xAE] = z80_inst_xor_ixy, [0xAF] = z80_inst_nop2, [0xB0] = z80_inst_nop2, [0xB1] = z80_inst_nop2, @@ -969,7 +969,7 @@ static DispatchTable instruction_table_index = { [0xBB] = z80_inst_nop2, [0xBC] = z80_inst_unimplemented, // TODO [0xBD] = z80_inst_unimplemented, // TODO - [0xBE] = z80_inst_unimplemented, // TODO + [0xBE] = z80_inst_cp_ixy, [0xBF] = z80_inst_nop2, [0xC0] = z80_inst_nop2, [0xC1] = z80_inst_nop2,