From f776379e968c2acccd2362ed52e7eaef35e5bcdf Mon Sep 17 00:00:00 2001 From: "Adrian.Conlon" Date: Thu, 22 Jun 2017 16:57:38 +0100 Subject: [PATCH] Share flag adjustments across implementations using templated methods. Signed-off-by: Adrian.Conlon --- Intel8080/inc/Intel8080.h | 31 +++------- Z80/inc/Z80.h | 9 --- Z80/src/Z80.cpp | 121 +++++++++++++------------------------- inc/IntelProcessor.h | 43 ++++++++++++++ 4 files changed, 92 insertions(+), 112 deletions(-) diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 02b9546..b06663d 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -83,21 +83,6 @@ namespace EightBit { F() |= Bit1; } - static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, SF, value & SF); } - static void adjustZero(uint8_t& f, uint8_t value) { clearFlag(f, ZF, value); } - - static void adjustParity(uint8_t& f, uint8_t value) { - static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; - auto set = (lookup[highNibble(value)] + lookup[lowNibble(value)]); - clearFlag(f, PF, set % 2); - } - - static void adjustSZP(uint8_t& f, uint8_t value) { - adjustSign(f, value); - adjustZero(f, value); - adjustParity(f, value); - } - static void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) { setFlag(f, AC, calculateHalfCarryAdd(before, value, calculation)); } @@ -107,12 +92,12 @@ namespace EightBit { } static void postIncrement(uint8_t& f, uint8_t value) { - adjustSZP(f, value); + adjustSZP(f, value); clearFlag(f, AC, lowNibble(value)); } static void postDecrement(uint8_t& f, uint8_t value) { - adjustSZP(f, value); + adjustSZP(f, value); setFlag(f, AC, lowNibble(value) != Mask4); } @@ -127,7 +112,7 @@ namespace EightBit { const auto& a = A(); auto& f = F(); uint16_t subtraction = a - value; - adjustSZP(f, (uint8_t)subtraction); + adjustSZP(f, (uint8_t)subtraction); adjustAuxiliaryCarrySub(f, a, value, subtraction); setFlag(f, CF, subtraction & Bit8); } @@ -137,19 +122,19 @@ namespace EightBit { auto& f = F(); setFlag(f, AC, (a | value) & Bit3); clearFlag(f, CF); - adjustSZP(f, a &= value); + adjustSZP(f, a &= value); } void ora(uint8_t value) { auto& f = F(); clearFlag(f, AC | CF); - adjustSZP(f, A() |= value); + adjustSZP(f, A() |= value); } void xra(uint8_t value) { auto& f = F(); clearFlag(f, AC | CF); - adjustSZP(f, A() ^= value); + adjustSZP(f, A() ^= value); } void add(uint8_t value, int carry = 0) { @@ -160,7 +145,7 @@ namespace EightBit { adjustAuxiliaryCarryAdd(f, a, value, sum.word); a = sum.low; setFlag(f, CF, sum.word & Bit8); - adjustSZP(f, a); + adjustSZP(f, a); } void adc(uint8_t value) { @@ -182,7 +167,7 @@ namespace EightBit { adjustAuxiliaryCarrySub(f, a, value, difference.word); a = difference.low; setFlag(f, CF, difference.word & Bit8); - adjustSZP(f, a); + adjustSZP(f, a); } void sbb(uint8_t value) { diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 7ce0009..545c0f8 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -253,15 +253,6 @@ namespace EightBit { void executeED(int x, int y, int z, int p, int q); void executeOther(int x, int y, int z, int p, int q); - static void adjustSign(uint8_t& f, uint8_t value); - static void adjustZero(uint8_t& f, uint8_t value); - static void adjustParity(uint8_t& f, uint8_t value); - static void adjustSZ(uint8_t& f, uint8_t value); - static void adjustSZP(uint8_t& f, uint8_t value); - static void adjustXY(uint8_t& f, uint8_t value); - static void adjustSZPXY(uint8_t& f, uint8_t value); - static void adjustSZXY(uint8_t& f, uint8_t value); - void postIncrement(uint8_t& f, uint8_t value); void postDecrement(uint8_t& f, uint8_t value); diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 3e9d769..b93bd04 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -106,54 +106,15 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) { #pragma region Flag manipulation helpers -void EightBit::Z80::adjustSign(uint8_t& f, uint8_t value) { - setFlag(f, SF, value & SF); -} - -void EightBit::Z80::adjustZero(uint8_t& f, uint8_t value) { - clearFlag(f, ZF, value); -} - -void EightBit::Z80::adjustParity(uint8_t& f, uint8_t value) { - static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; - auto set = lookup[highNibble(value)] + lookup[lowNibble(value)]; - clearFlag(f, PF, set % 2); -} - -void EightBit::Z80::adjustSZ(uint8_t& f, uint8_t value) { - adjustSign(f, value); - adjustZero(f, value); -} - -void EightBit::Z80::adjustSZP(uint8_t& f, uint8_t value) { - adjustSZ(f, value); - adjustParity(f, value); -} - -void EightBit::Z80::adjustXY(uint8_t& f, uint8_t value) { - setFlag(f, XF, value & XF); - setFlag(f, YF, value & YF); -} - -void EightBit::Z80::adjustSZPXY(uint8_t& f, uint8_t value) { - adjustSZP(f, value); - adjustXY(f, value); -} - -void EightBit::Z80::adjustSZXY(uint8_t& f, uint8_t value) { - adjustSZ(f, value); - adjustXY(f, value); -} - void EightBit::Z80::postIncrement(uint8_t& f, uint8_t value) { - adjustSZXY(f, value); + adjustSZXY(f, value); clearFlag(f, NF); setFlag(f, VF, value == Bit7); clearFlag(f, HC, lowNibble(value)); } void EightBit::Z80::postDecrement(uint8_t& f, uint8_t value) { - adjustSZXY(f, value); + adjustSZXY(f, value); setFlag(f, NF); setFlag(f, VF, value == Mask7); clearFlag(f, HC, lowNibble(value + 1)); @@ -284,7 +245,7 @@ void EightBit::Z80::sbc(register16_t& operand, register16_t value) { adjustOverflowSub(f, beforeNegative, valueNegative, afterNegative); setFlag(f, NF); setFlag(f, CF, result & Bit16); - adjustXY(f, operand.high); + adjustXY(f, operand.high); } void EightBit::Z80::adc(register16_t& operand, register16_t value) { @@ -307,7 +268,7 @@ void EightBit::Z80::adc(register16_t& operand, register16_t value) { adjustOverflowAdd(f, beforeNegative, valueNegative, afterNegative); clearFlag(f, NF); setFlag(f, CF, result & Bit16); - adjustXY(f, operand.high); + adjustXY(f, operand.high); } void EightBit::Z80::add(register16_t& operand, register16_t value) { @@ -323,7 +284,7 @@ void EightBit::Z80::add(register16_t& operand, register16_t value) { clearFlag(f, NF); setFlag(f, CF, result & Bit16); adjustHalfCarryAdd(f, before.high, value.high, operand.high); - adjustXY(f, operand.high); + adjustXY(f, operand.high); } #pragma endregion 16-bit arithmetic @@ -344,7 +305,7 @@ void EightBit::Z80::add(uint8_t& operand, uint8_t value, int carry) { clearFlag(f, NF); setFlag(f, CF, result.word & Bit8); - adjustSZXY(f, operand); + adjustSZXY(f, operand); } void EightBit::Z80::adc(uint8_t& operand, uint8_t value) { @@ -365,7 +326,7 @@ void EightBit::Z80::sub(uint8_t& operand, uint8_t value, int carry) { setFlag(f, NF); setFlag(f, CF, result.word & Bit8); - adjustSZXY(f, operand); + adjustSZXY(f, operand); } void EightBit::Z80::sbc(uint8_t& operand, uint8_t value) { @@ -377,28 +338,28 @@ void EightBit::Z80::andr(uint8_t& operand, uint8_t value) { operand &= value; setFlag(f, HC); clearFlag(f, CF | NF); - adjustSZPXY(f, operand); + adjustSZPXY(f, operand); } void EightBit::Z80::xorr(uint8_t& operand, uint8_t value) { auto& f = F(); operand ^= value; clearFlag(f, HC | CF | NF); - adjustSZPXY(f, operand); + adjustSZPXY(f, operand); } void EightBit::Z80::orr(uint8_t& operand, uint8_t value) { auto& f = F(); operand |= value; clearFlag(f, HC | CF | NF); - adjustSZPXY(f, operand); + adjustSZPXY(f, operand); } void EightBit::Z80::compare(uint8_t value) { auto& f = F(); auto check = A(); sub(check, value); - adjustXY(f, value); + adjustXY(f, value); } #pragma endregion ALU @@ -412,7 +373,7 @@ uint8_t& EightBit::Z80::rlc(uint8_t& operand) { carry ? operand |= Bit0 : operand &= ~Bit0; setFlag(f, CF, carry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -423,7 +384,7 @@ uint8_t& EightBit::Z80::rrc(uint8_t& operand) { carry ? operand |= Bit7 : operand &= ~Bit7; setFlag(f, CF, carry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -435,7 +396,7 @@ uint8_t& EightBit::Z80::rl(uint8_t& operand) { oldCarry ? operand |= Bit0 : operand &= ~Bit0; setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -447,7 +408,7 @@ uint8_t& EightBit::Z80::rr(uint8_t& operand) { operand |= oldCarry << 7; setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -459,7 +420,7 @@ uint8_t& EightBit::Z80::sla(uint8_t& operand) { operand <<= 1; setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -471,7 +432,7 @@ uint8_t& EightBit::Z80::sra(uint8_t& operand) { operand |= new7; setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -482,7 +443,7 @@ uint8_t& EightBit::Z80::sll(uint8_t& operand) { operand |= 1; setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); return operand; } @@ -493,7 +454,7 @@ uint8_t& EightBit::Z80::srl(uint8_t& operand) { operand &= ~Bit7; // clear bit 7 setFlag(f, CF, newCarry); clearFlag(f, NF | HC); - adjustXY(f, operand); + adjustXY(f, operand); setFlag(f, ZF, operand); return operand; } @@ -562,7 +523,7 @@ void EightBit::Z80::daa() { f = (f & (CF | NF)) | (acc > 0x99) | ((acc ^ a) & HC); - adjustSZPXY(f, a); + adjustSZPXY(f, a); acc = a; } @@ -571,14 +532,14 @@ void EightBit::Z80::cpl() { auto& a = A(); auto& f = F(); a = ~a; - adjustXY(f, A()); + adjustXY(f, A()); setFlag(f, HC | NF); } void EightBit::Z80::scf() { auto& f = F(); setFlag(f, CF); - adjustXY(f, A()); + adjustXY(f, A()); clearFlag(f, HC | NF); } @@ -588,7 +549,7 @@ void EightBit::Z80::ccf() { setFlag(f, HC, carry); clearFlag(f, CF, carry); clearFlag(f, NF); - adjustXY(f, A()); + adjustXY(f, A()); } void EightBit::Z80::xhtl(register16_t& operand) { @@ -624,7 +585,7 @@ void EightBit::Z80::blockCompare() { setFlag(f, PF, --BC().word); - adjustSZ(f, result); + adjustSZ(f, result); adjustHalfCarrySub(f, a, value, result); setFlag(f, NF); @@ -760,7 +721,7 @@ void EightBit::Z80::blockOut() { postDecrement(f, --B()); setFlag(f, NF, value & Bit7); setFlag(f, HC | CF, (L() + value) > 0xff); - adjustParity(f, ((value + L()) & 7) ^ B()); + adjustParity(f, ((value + L()) & 7) ^ B()); } void EightBit::Z80::outi() { @@ -798,7 +759,7 @@ void EightBit::Z80::rrd() { auto memory = memptrReference(); m_memory.reference() = promoteNibble(a) | highNibble(memory); a = (a & 0xf0) | lowNibble(memory); - adjustSZPXY(f, a); + adjustSZPXY(f, a); clearFlag(f, NF | HC); } @@ -809,7 +770,7 @@ void EightBit::Z80::rld() { auto memory = memptrReference(); m_memory.reference() = promoteNibble(memory) | lowNibble(a); a = (a & 0xf0) | highNibble(memory); - adjustSZPXY(f, a); + adjustSZPXY(f, a); clearFlag(f, NF | HC); } @@ -858,28 +819,28 @@ void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) { case 0: // rot[y] r[z] switch (y) { case 0: - adjustSZP(f, m_displaced ? R2(z) = rlc(DISPLACED()) : rlc(R(z))); + adjustSZP(f, m_displaced ? R2(z) = rlc(DISPLACED()) : rlc(R(z))); break; case 1: - adjustSZP(f, m_displaced ? R2(z) = rrc(DISPLACED()) : rrc(R(z))); + adjustSZP(f, m_displaced ? R2(z) = rrc(DISPLACED()) : rrc(R(z))); break; case 2: - adjustSZP(f, m_displaced ? R2(z) = rl(DISPLACED()) : rl(R(z))); + adjustSZP(f, m_displaced ? R2(z) = rl(DISPLACED()) : rl(R(z))); break; case 3: - adjustSZP(f, m_displaced ? R2(z) = rr(DISPLACED()) : rr(R(z))); + adjustSZP(f, m_displaced ? R2(z) = rr(DISPLACED()) : rr(R(z))); break; case 4: - adjustSZP(f, m_displaced ? R2(z) = sla(DISPLACED()) : sla(R(z))); + adjustSZP(f, m_displaced ? R2(z) = sla(DISPLACED()) : sla(R(z))); break; case 5: - adjustSZP(f, m_displaced ? R2(z) = sra(DISPLACED()) : sra(R(z))); + adjustSZP(f, m_displaced ? R2(z) = sra(DISPLACED()) : sra(R(z))); break; case 6: - adjustSZP(f, m_displaced ? R2(z) = sll(DISPLACED()) : sll(R(z))); + adjustSZP(f, m_displaced ? R2(z) = sll(DISPLACED()) : sll(R(z))); break; case 7: - adjustSZP(f, m_displaced ? R2(z) = srl(DISPLACED()) : srl(R(z))); + adjustSZP(f, m_displaced ? R2(z) = srl(DISPLACED()) : srl(R(z))); break; } if (m_displaced) { @@ -893,16 +854,16 @@ void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) { case 1: // BIT y, r[z] if (m_displaced) { bit(y, DISPLACED()); - adjustXY(f, MEMPTR().high); + adjustXY(f, MEMPTR().high); cycles += 20; } else { auto operand = bit(y, R(z)); cycles += 8; if (z == 6) { - adjustXY(f, MEMPTR().high); + adjustXY(f, MEMPTR().high); cycles += 4; } else { - adjustXY(f, operand); + adjustXY(f, operand); } } break; @@ -946,7 +907,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) { readPort(); if (y != 6) // IN r[y],(C) R(y) = m_memory.DATA(); - adjustSZPXY(f, m_memory.DATA()); + adjustSZPXY(f, m_memory.DATA()); clearFlag(f, NF | HC); cycles += 12; break; @@ -1031,14 +992,14 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) { break; case 2: // LD A,I A() = IV(); - adjustSZXY(f, A()); + adjustSZXY(f, A()); setFlag(f, PF, IFF2()); clearFlag(f, NF | HC); cycles += 9; break; case 3: // LD A,R A() = REFRESH(); - adjustSZXY(f, A()); + adjustSZXY(f, A()); clearFlag(f, NF | HC); setFlag(f, PF, IFF2()); cycles += 9; diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index 3927f07..d6fe05d 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -43,6 +43,49 @@ namespace EightBit { static void clearFlag(uint8_t& f, int flag, uint32_t condition) { clearFlag(f, flag, condition != 0); } static void clearFlag(uint8_t& f, int flag, bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); } + // + + template static void adjustSign(uint8_t& f, uint8_t value) { + setFlag(f, T::SF, value & T::SF); + } + + template static void adjustZero(uint8_t& f, uint8_t value) { + clearFlag(f, T::ZF, value); + } + + template static void adjustParity(uint8_t& f, uint8_t value) { + static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + auto set = lookup[highNibble(value)] + lookup[lowNibble(value)]; + clearFlag(f, T::PF, set % 2); + } + + template static void adjustSZ(uint8_t& f, uint8_t value) { + adjustSign(f, value); + adjustZero(f, value); + } + + template static void adjustSZP(uint8_t& f, uint8_t value) { + adjustSZ(f, value); + adjustParity(f, value); + } + + template static void adjustXY(uint8_t& f, uint8_t value) { + setFlag(f, T::XF, value & T::XF); + setFlag(f, T::YF, value & T::YF); + } + + template static void adjustSZPXY(uint8_t& f, uint8_t value) { + adjustSZP(f, value); + adjustXY(f, value); + } + + template static void adjustSZXY(uint8_t& f, uint8_t value) { + adjustSZ(f, value); + adjustXY(f, value); + } + + // + static int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) { return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3); }