From 8f18a128cd991a759c897cab5e28ada5f3efc2cd Mon Sep 17 00:00:00 2001 From: "Adrian.Conlon" Date: Sat, 22 Jul 2017 23:52:58 +0100 Subject: [PATCH] First step of moving to an instruction decoder, rather than a lookup table. Signed-off-by: Adrian.Conlon --- Intel8080/inc/Intel8080.h | 230 ++++++------------------- Intel8080/src/Intel8080.cpp | 329 ++++++++++++++++++++++++++++++++++++ 2 files changed, 383 insertions(+), 176 deletions(-) diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 5a78849..81aaa4c 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -43,17 +43,9 @@ namespace EightBit { virtual register16_t& DE() override { return de; } virtual register16_t& HL() override { return hl; } - bool isInterruptable() const { - return m_interrupt; - } + bool isInterruptable() const; - int interrupt(uint8_t value) { - if (isInterruptable()) { - di(); - return execute(value); - } - return 0; - } + int interrupt(uint8_t value); virtual void initialise(); int step(); @@ -72,11 +64,7 @@ namespace EightBit { int execute(uint8_t opcode); - int execute(const Instruction& instruction) { - cycles = 0; - instruction.vector(); - return cycles + instruction.count; - } + int execute(const Instruction& instruction); void adjustReservedFlags() { F() = (F() | Bit1) & ~(Bit5 | Bit3); @@ -90,15 +78,9 @@ namespace EightBit { clearFlag(f, AC, calculateHalfCarrySub(before, value, calculation)); } - static void increment(uint8_t& f, uint8_t& operand) { - adjustSZP(f, ++operand); - clearFlag(f, AC, lowNibble(operand)); - } + static void increment(uint8_t& f, uint8_t& operand); - static void decrement(uint8_t& f, uint8_t& operand) { - adjustSZP(f, --operand); - setFlag(f, AC, lowNibble(operand) != Mask4); - } + static void decrement(uint8_t& f, uint8_t& operand); static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles); Instruction UNKNOWN(); @@ -107,68 +89,18 @@ namespace EightBit { // - void compare(uint8_t& f, uint8_t check, uint8_t value) { - subtract(f, check, value); - } + void compare(uint8_t& f, uint8_t check, uint8_t value); + void anda(uint8_t value); + void ora(uint8_t value); + void xra(uint8_t value); - void anda(uint8_t value) { - auto& a = A(); - auto& f = F(); - setFlag(f, AC, (a | value) & Bit3); - clearFlag(f, CF); - adjustSZP(f, a &= value); - } + void add(uint8_t value, int carry = 0); + void adc(uint8_t value); - void ora(uint8_t value) { - auto& f = F(); - clearFlag(f, AC | CF); - adjustSZP(f, A() |= value); - } + void dad(uint16_t value); - void xra(uint8_t value) { - auto& f = F(); - clearFlag(f, AC | CF); - adjustSZP(f, A() ^= value); - } - - void add(uint8_t value, int carry = 0) { - auto& a = A(); - auto& f = F(); - register16_t sum; - sum.word = a + value + carry; - adjustAuxiliaryCarryAdd(f, a, value, sum.word); - a = sum.low; - setFlag(f, CF, sum.word & Bit8); - adjustSZP(f, a); - } - - void adc(uint8_t value) { - add(value, F() & CF); - } - - void dad(uint16_t value) { - auto& f = F(); - auto sum = HL().word + value; - setFlag(f, CF, sum & Bit16); - HL().word = sum; - } - - void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0) { - - register16_t result; - result.word = operand - value - carry; - - adjustAuxiliaryCarrySub(f, operand, value, result.word); - - operand = result.low; - - setFlag(f, CF, result.word & Bit8); - adjustSZP(f, operand); - } - - void sbb(uint8_t value) { - subtract(F(), A(), value, F() & CF); - } + void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0); + void sbb(uint8_t value); void mov_m_r(uint8_t value) { m_memory.ADDRESS() = HL(); @@ -332,16 +264,7 @@ namespace EightBit { adjustReservedFlags(); } - void xhtl() { - m_memory.ADDRESS() = SP(); - MEMPTR().low = m_memory.reference(); - m_memory.reference() = L(); - L() = MEMPTR().low; - m_memory.ADDRESS().word++; - MEMPTR().high = m_memory.reference(); - m_memory.reference() = H(); - H() = MEMPTR().high; - } + void xhtl(); void sphl() { SP() = HL(); @@ -356,56 +279,51 @@ namespace EightBit { // jump - void jmp() { jumpConditional(true); } + void jmp(); - void jc() { jumpConditional(F() & CF); } - void jnc() { jumpConditional(!(F() & CF)); } + void jc(); + void jnc(); - void jz() { jumpConditional(F() & ZF); } - void jnz() { jumpConditional(!(F() & ZF)); } + void jz(); + void jnz(); - void jpe() { jumpConditional(F() & PF); } - void jpo() { jumpConditional(!(F() & PF)); } + void jpe(); + void jpo(); - void jm() { jumpConditional(F() & SF); } - void jp() { jumpConditional(!(F() & SF)); } + void jm(); + void jp(); - void pchl() { - PC() = HL(); - } + void pchl(); // call - void callDirect() { - fetchWord(); - call(); - } + void callDirect(); - void cc() { if (callConditional(F() & CF)) cycles += 6; } - void cnc() { if (callConditional(!(F() & CF))) cycles += 6; } + void cc(); + void cnc(); - void cpe() { if (callConditional(F() & PF)) cycles += 6; } - void cpo() { if (callConditional(!(F() & PF))) cycles += 6; } + void cpe(); + void cpo(); - void cz() { if (callConditional(F() & ZF)) cycles += 6; } - void cnz() { if (callConditional(!(F() & ZF))) cycles += 6; } + void cz(); + void cnz(); - void cm() { if (callConditional(F() & SF)) cycles += 6; } - void cp() { if (callConditional(!(F() & SF))) cycles += 6; } + void cm(); + void cp(); // return - void rc() { if (returnConditional(F() & CF)) cycles += 6; } - void rnc() { if (returnConditional(!(F() & CF))) cycles += 6; } + void rc(); + void rnc(); - void rz() { if (returnConditional(F() & ZF)) cycles += 6; } - void rnz() { if (returnConditional(!(F() & ZF))) cycles += 6; } + void rz(); + void rnz(); - void rpe() { if (returnConditional(F() & PF)) cycles += 6; } - void rpo() { if (returnConditional(!(F() & PF))) cycles += 6; } + void rpe(); + void rpo(); - void rm() { if (returnConditional(F() & SF)) cycles += 6; } - void rp() { if (returnConditional(!(F() & SF))) cycles += 6; } + void rm(); + void rp(); // restart @@ -591,67 +509,27 @@ namespace EightBit { // rotate - void rlc() { - auto& a = A(); - auto carry = a & Bit7; - a = (a << 1) | (carry >> 7); - setFlag(F(), CF, carry); - } - - void rrc() { - auto& a = A(); - auto carry = a & Bit0; - a = (a >> 1) | (carry << 7); - setFlag(F(), CF, carry); - } - - void ral() { - auto& a = A(); - auto& f = F(); - const auto carry = f & CF; - setFlag(f, CF, a & Bit7); - a = (a << 1) | carry; - } - - void rar() { - auto& a = A(); - auto& f = F(); - const auto carry = f & CF; - setFlag(f, CF, a & Bit0); - a = (a >> 1) | (carry << 7); - } + void rlc(); + void rrc(); + void ral(); + void rar(); // specials - void cma() { A() ^= Mask8; } - void stc() { setFlag(F(), CF); } - void cmc() { clearFlag(F(), CF, F() & CF); } - - void daa() { - const auto& a = A(); - auto& f = F(); - auto carry = f & CF; - uint8_t addition = 0; - if ((f & AC) || lowNibble(a) > 9) { - addition = 0x6; - } - if ((f & CF) || highNibble(a) > 9 || (highNibble(a) >= 9 && lowNibble(a) > 9)) { - addition |= 0x60; - carry = true; - } - add(addition); - setFlag(f, CF, carry); - } + void cma(); + void stc(); + void cmc(); + void daa(); // input/output - void out() { m_ports.write(fetchByte(), A()); } - void in() { A() = m_ports.read(fetchByte()); } + void out(); + void in(); // control - void ei() { m_interrupt = true; } - void di() { m_interrupt = false; } + void ei(); + void di(); void nop() {} diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index 41be661..2850369 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -62,6 +62,329 @@ void EightBit::Intel8080::initialise() { AF().word = BC().word = DE().word = HL().word = 0; } +#pragma region Interrupt routines + +void EightBit::Intel8080::di() { + m_interrupt = false; +} + +void EightBit::Intel8080::ei() { + m_interrupt = true; +} + +int EightBit::Intel8080::interrupt(uint8_t value) { + if (isInterruptable()) { + di(); + return execute(value); + } + return 0; +} + +bool EightBit::Intel8080::isInterruptable() const { + return m_interrupt; +} + +#pragma endregion Interrupt routines + +#pragma region Flag manipulation helpers + +void EightBit::Intel8080::increment(uint8_t& f, uint8_t& operand) { + adjustSZP(f, ++operand); + clearFlag(f, AC, lowNibble(operand)); +} + +void EightBit::Intel8080::decrement(uint8_t& f, uint8_t& operand) { + adjustSZP(f, --operand); + setFlag(f, AC, lowNibble(operand) != Mask4); +} + +#pragma endregion Flag manipulation helpers + +#pragma region PC manipulation: call/ret/jp/jr + +void EightBit::Intel8080::jmp() { + jumpConditional(true); +} + +void EightBit::Intel8080::jc() { + jumpConditional(F() & CF); +} + +void EightBit::Intel8080::jnc() { + jumpConditional(!(F() & CF)); +} + +void EightBit::Intel8080::jz() { + jumpConditional(F() & ZF); +} + +void EightBit::Intel8080::jnz() { + jumpConditional(!(F() & ZF)); +} + +void EightBit::Intel8080::jpe() { + jumpConditional(F() & PF); +} + +void EightBit::Intel8080::jpo() { + jumpConditional(!(F() & PF)); +} + +void EightBit::Intel8080::jm() { + jumpConditional(F() & SF); +} + +void EightBit::Intel8080::jp() { + jumpConditional(!(F() & SF)); +} + +void EightBit::Intel8080::pchl() { + PC() = HL(); +} + +void EightBit::Intel8080::rc() { + if (returnConditional(F() & CF)) + cycles += 6; +} + +void EightBit::Intel8080::rnc() { + if (returnConditional(!(F() & CF))) + cycles += 6; +} + +void EightBit::Intel8080::rz() { + if (returnConditional(F() & ZF)) + cycles += 6; +} + +void EightBit::Intel8080::rnz() { + if (returnConditional(!(F() & ZF))) + cycles += 6; +} + +void EightBit::Intel8080::rpe() { + if (returnConditional(F() & PF)) + cycles += 6; +} + +void EightBit::Intel8080::rpo() { + if (returnConditional(!(F() & PF))) + cycles += 6; +} + +void EightBit::Intel8080::rm() { + if (returnConditional(F() & SF)) + cycles += 6; +} + +void EightBit::Intel8080::rp() { + if (returnConditional(!(F() & SF))) + cycles += 6; +} + +void EightBit::Intel8080::callDirect() { + fetchWord(); + call(); +} + +void EightBit::Intel8080::cc() { + if (callConditional(F() & CF)) + cycles += 6; +} + +void EightBit::Intel8080::cnc() { + if (callConditional(!(F() & CF))) + cycles += 6; +} + +void EightBit::Intel8080::cpe() { + if (callConditional(F() & PF)) + cycles += 6; +} + +void EightBit::Intel8080::cpo() { + if (callConditional(!(F() & PF))) + cycles += 6; +} + +void EightBit::Intel8080::cz() { + if (callConditional(F() & ZF)) + cycles += 6; +} + +void EightBit::Intel8080::cnz() { + if (callConditional(!(F() & ZF))) + cycles += 6; +} + +void EightBit::Intel8080::cm() { + if (callConditional(F() & SF)) + cycles += 6; +} + +void EightBit::Intel8080::cp() { + if (callConditional(!(F() & SF))) + cycles += 6; +} + +#pragma endregion PC manipulation: call/ret/jp/jr + +#pragma region 16-bit arithmetic + +void EightBit::Intel8080::dad(uint16_t value) { + auto& f = F(); + auto sum = HL().word + value; + setFlag(f, CF, sum & Bit16); + HL().word = sum; +} + +#pragma endregion 16-bit arithmetic + +#pragma region ALU + +void EightBit::Intel8080::add(uint8_t value, int carry) { + auto& a = A(); + auto& f = F(); + register16_t sum; + sum.word = a + value + carry; + adjustAuxiliaryCarryAdd(f, a, value, sum.word); + a = sum.low; + setFlag(f, CF, sum.word & Bit8); + adjustSZP(f, a); +} + +void EightBit::Intel8080::adc(uint8_t value) { + add(value, F() & CF); +} + +void EightBit::Intel8080::subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry) { + + register16_t result; + result.word = operand - value - carry; + + adjustAuxiliaryCarrySub(f, operand, value, result.word); + + operand = result.low; + + setFlag(f, CF, result.word & Bit8); + adjustSZP(f, operand); +} + +void EightBit::Intel8080::sbb(uint8_t value) { + subtract(F(), A(), value, F() & CF); +} + +void EightBit::Intel8080::anda(uint8_t value) { + auto& a = A(); + auto& f = F(); + setFlag(f, AC, (a | value) & Bit3); + clearFlag(f, CF); + adjustSZP(f, a &= value); +} + +void EightBit::Intel8080::xra(uint8_t value) { + auto& f = F(); + clearFlag(f, AC | CF); + adjustSZP(f, A() ^= value); +} + +void EightBit::Intel8080::ora(uint8_t value) { + auto& f = F(); + clearFlag(f, AC | CF); + adjustSZP(f, A() |= value); +} + +void EightBit::Intel8080::compare(uint8_t& f, uint8_t check, uint8_t value) { + subtract(f, check, value); +} + +#pragma endregion ALU + +#pragma region Shift and rotate + +void EightBit::Intel8080::rlc() { + auto& a = A(); + auto carry = a & Bit7; + a = (a << 1) | (carry >> 7); + setFlag(F(), CF, carry); +} + +void EightBit::Intel8080::rrc() { + auto& a = A(); + auto carry = a & Bit0; + a = (a >> 1) | (carry << 7); + setFlag(F(), CF, carry); +} + +void EightBit::Intel8080::ral() { + auto& a = A(); + auto& f = F(); + const auto carry = f & CF; + setFlag(f, CF, a & Bit7); + a = (a << 1) | carry; +} + +void EightBit::Intel8080::rar() { + auto& a = A(); + auto& f = F(); + const auto carry = f & CF; + setFlag(f, CF, a & Bit0); + a = (a >> 1) | (carry << 7); +} + +#pragma endregion Shift and rotate + +#pragma region Miscellaneous instructions + +void EightBit::Intel8080::daa() { + const auto& a = A(); + auto& f = F(); + auto carry = f & CF; + uint8_t addition = 0; + if ((f & AC) || lowNibble(a) > 9) { + addition = 0x6; + } + if ((f & CF) || highNibble(a) > 9 || (highNibble(a) >= 9 && lowNibble(a) > 9)) { + addition |= 0x60; + carry = true; + } + add(addition); + setFlag(f, CF, carry); +} + +void EightBit::Intel8080::cma() { + A() ^= Mask8; +} + +void EightBit::Intel8080::stc() { + setFlag(F(), CF); +} + +void EightBit::Intel8080::cmc() { + clearFlag(F(), CF, F() & CF); +} + +void EightBit::Intel8080::xhtl() { + m_memory.ADDRESS() = SP(); + MEMPTR().low = m_memory.reference(); + m_memory.reference() = L(); + L() = MEMPTR().low; + m_memory.ADDRESS().word++; + MEMPTR().high = m_memory.reference(); + m_memory.reference() = H(); + H() = MEMPTR().high; +} + +#pragma endregion Miscellaneous instructions + +void EightBit::Intel8080::out() { + m_ports.write(fetchByte(), A()); +} + +void EightBit::Intel8080::in() { + A() = m_ports.read(fetchByte()); +} + int EightBit::Intel8080::step() { ExecutingInstruction.fire(*this); return execute(fetchByte()); @@ -72,6 +395,12 @@ int EightBit::Intel8080::execute(uint8_t opcode) { return execute(instruction); } +int EightBit::Intel8080::execute(const Instruction& instruction) { + cycles = 0; + instruction.vector(); + return cycles + instruction.count; +} + // void EightBit::Intel8080::___() {