From 675b82b5afb1255b4199d0a9e89889fbabfb6376 Mon Sep 17 00:00:00 2001 From: "Adrian.Conlon" Date: Fri, 16 Jun 2017 01:58:12 +0100 Subject: [PATCH] Move to a more standard flag representation for the 8080 --- Intel8080/inc/Disassembler.h | 2 + Intel8080/inc/Intel8080.h | 160 +++++++++++++----------- Intel8080/inc/StatusFlags.h | 72 ----------- Intel8080/src/Disassembler.cpp | 23 +++- Intel8080/src/Intel8080.cpp | 11 +- Intel8080/src/Intel8080.vcxproj | 1 - Intel8080/src/Intel8080.vcxproj.filters | 3 - 7 files changed, 113 insertions(+), 159 deletions(-) delete mode 100644 Intel8080/inc/StatusFlags.h diff --git a/Intel8080/inc/Disassembler.h b/Intel8080/inc/Disassembler.h index baa4735..b3d4699 100644 --- a/Intel8080/inc/Disassembler.h +++ b/Intel8080/inc/Disassembler.h @@ -12,6 +12,8 @@ namespace EightBit { static std::string state(Intel8080& cpu); static std::string disassemble(Intel8080& cpu); + static std::string flag(uint8_t value, int flag, const std::string& represents); + static std::string flags(uint8_t value); static std::string hex(uint8_t value); static std::string hex(uint16_t value); static std::string binary(uint8_t value); diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index e82a1db..d0dd064 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -3,7 +3,6 @@ // Auxiliary carry logic from https://github.com/begoon/i8080-core #include "IntelProcessor.h" -#include "StatusFlags.h" #include "InputOutput.h" namespace EightBit { @@ -11,6 +10,14 @@ namespace EightBit { public: typedef std::function instruction_t; + enum StatusBits { + SF = Bit7, + ZF = Bit6, + AC = Bit4, + PF = Bit2, + CF = Bit0, + }; + enum AddressingMode { Unknown, Implied, // zero bytes @@ -31,8 +38,14 @@ namespace EightBit { const std::array& getInstructions() const { return instructions; } - uint8_t& A() { return a; } - StatusFlags& F() { return f; } + register16_t& AF() { + af.low &= ~(Bit5 | Bit3); + af.low |= Bit1; + return af; + } + + uint8_t& A() { return AF().high; } + uint8_t& F() { return AF().low; } register16_t& BC() { return bc; } uint8_t& B() { return BC().high; } @@ -66,15 +79,24 @@ namespace EightBit { std::array instructions; - uint8_t a; - StatusFlags f; - + register16_t af; register16_t bc; register16_t de; register16_t hl; bool m_interrupt; + void clearFlag(int flag) { F() &= ~flag; } + void setFlag(int flag) { F() |= flag; } + + void setFlag(int flag, int condition) { setFlag(flag, condition != 0); } + void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); } + void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); } + + void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); } + void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); } + void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); } + int execute(uint8_t opcode); int execute(const Instruction& instruction) { @@ -83,13 +105,13 @@ namespace EightBit { return cycles + instruction.count; } - void adjustSign(uint8_t value) { F().S = ((value & Bit7) != 0); } - void adjustZero(uint8_t value) { F().Z = !value; } + void adjustSign(uint8_t value) { setFlag(SF, value & SF); } + void adjustZero(uint8_t value) { clearFlag(ZF, value);} void adjustParity(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)]); - F().P = !(set % 2); + clearFlag(PF, set % 2); } void adjustSZP(uint8_t value) { @@ -99,21 +121,21 @@ namespace EightBit { } void adjustAuxiliaryCarryAdd(uint8_t value, int calculation) { - F().AC = calculateHalfCarryAdd(A(), value, calculation); + setFlag(AC, calculateHalfCarryAdd(A(), value, calculation)); } void adjustAuxiliaryCarrySub(uint8_t value, int calculation) { - F().AC = !calculateHalfCarrySub(A(), value, calculation); + clearFlag(AC, calculateHalfCarrySub(A(), value, calculation)); } void postIncrement(uint8_t value) { adjustSZP(value); - F().AC = !lowNibble(value); + clearFlag(AC, lowNibble(value)); } void postDecrement(uint8_t value) { adjustSZP(value); - F().AC = lowNibble(value) != Mask4; + setFlag(AC, lowNibble(value) != Mask4); } static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles); @@ -127,22 +149,22 @@ namespace EightBit { uint16_t subtraction = A() - value; adjustSZP((uint8_t)subtraction); adjustAuxiliaryCarrySub(value, subtraction); - F().C = (subtraction & Bit8) != 0; + setFlag(CF, subtraction & Bit8); } void anda(uint8_t value) { - F().AC = (((A() | value) & Bit3) != 0); - F().C = false; + setFlag(AC, (A() | value) & Bit3); + clearFlag(CF); adjustSZP(A() &= value); } void ora(uint8_t value) { - F().AC = F().C = false; + clearFlag(AC | CF); adjustSZP(A() |= value); } void xra(uint8_t value) { - F().AC = F().C = false; + clearFlag(AC | CF); adjustSZP(A() ^= value); } @@ -151,17 +173,17 @@ namespace EightBit { sum.word = A() + value + carry; adjustAuxiliaryCarryAdd(value, sum.word); A() = sum.low; - F().C = (sum.word & Bit8) != 0; + setFlag(CF, sum.word & Bit8); adjustSZP(A()); } void adc(uint8_t value) { - add(value, F().C); + add(value, F() & CF); } void dad(uint16_t value) { uint32_t sum = HL().word + value; - F().C = sum > 0xffff; + setFlag(CF, sum > 0xffff); HL().word = (uint16_t)sum; } @@ -170,12 +192,12 @@ namespace EightBit { difference.word = A() - value - carry; adjustAuxiliaryCarrySub(value, difference.word); A() = difference.low; - F().C = (difference.word & Bit8) != 0; + setFlag(CF, difference.word & Bit8); adjustSZP(A()); } void sbb(uint8_t value) { - sub(value, F().C); + sub(value, F() & CF); } void mov_m_r(uint8_t value) { @@ -316,22 +338,12 @@ namespace EightBit { void push_b() { pushWord(BC()); } void push_d() { pushWord(DE()); } void push_h() { pushWord(HL()); } - - void push_psw() { - register16_t pair; - pair.low = F(); - pair.high = A(); - pushWord(pair); - } + void push_psw() { pushWord(AF()); } void pop_b() { popWord(BC()); } void pop_d() { popWord(DE()); } void pop_h() { popWord(HL()); } - - void pop_psw() { - F() = pop(); - A() = pop(); - } + void pop_psw() { popWord(AF()); } void xhtl() { auto tos = m_memory.getWord(sp.word); @@ -354,17 +366,17 @@ namespace EightBit { void jmp() { jumpConditional(true); } - void jc() { jumpConditional(F().C); } - void jnc() { jumpConditional(!F().C); } + void jc() { jumpConditional(F() & CF); } + void jnc() { jumpConditional(!(F() & CF)); } - void jz() { jumpConditional(F().Z); } - void jnz() { jumpConditional(!F().Z); } + void jz() { jumpConditional(F() & ZF); } + void jnz() { jumpConditional(!(F() & ZF)); } - void jpe() { jumpConditional(F().P); } - void jpo() { jumpConditional(!F().P); } + void jpe() { jumpConditional(F() & PF); } + void jpo() { jumpConditional(!(F() & PF)); } - void jm() { jumpConditional(F().S); } - void jp() { jumpConditional(!F().S); } + void jm() { jumpConditional(F() & SF); } + void jp() { jumpConditional(!(F() & SF)); } void pchl() { pc = HL(); @@ -377,31 +389,31 @@ namespace EightBit { call(); } - void cc() { if (callConditional(F().C)) cycles += 6; } - void cnc() { if (callConditional(!F().C)) cycles += 6; } + void cc() { if (callConditional(F() & CF)) cycles += 6; } + void cnc() { if (callConditional(!(F() & CF))) cycles += 6; } - void cpe() { if (callConditional(F().P)) cycles += 6; } - void cpo() { if (callConditional(!F().P)) cycles += 6; } + void cpe() { if (callConditional(F() & PF)) cycles += 6; } + void cpo() { if (callConditional(!(F() & PF))) cycles += 6; } - void cz() { if (callConditional(F().Z)) cycles += 6; } - void cnz() { if (callConditional(!F().Z)) cycles += 6; } + void cz() { if (callConditional(F() & ZF)) cycles += 6; } + void cnz() { if (callConditional(!(F() & ZF))) cycles += 6; } - void cm() { if (callConditional(F().S)) cycles += 6; } - void cp() { if (callConditional(!F().S)) cycles += 6; } + void cm() { if (callConditional(F() & SF)) cycles += 6; } + void cp() { if (callConditional(!(F() & SF))) cycles += 6; } // return - void rc() { if (returnConditional(F().C)) cycles += 6; } - void rnc() { if (returnConditional(!F().C)) cycles += 6; } + void rc() { if (returnConditional(F() & CF)) cycles += 6; } + void rnc() { if (returnConditional(!(F() & CF))) cycles += 6; } - void rz() { if (returnConditional(F().Z)) cycles += 6; } - void rnz() { if (returnConditional(!F().Z)) cycles += 6; } + void rz() { if (returnConditional(F() & ZF)) cycles += 6; } + void rnz() { if (returnConditional(!(F() & ZF))) cycles += 6; } - void rpe() { if (returnConditional(F().P)) cycles += 6; } - void rpo() { if (returnConditional(!F().P)) cycles += 6; } + void rpe() { if (returnConditional(F() & PF)) cycles += 6; } + void rpo() { if (returnConditional(!(F() & PF))) cycles += 6; } - void rm() { if (returnConditional(F().S)) cycles += 6; } - void rp() { if (returnConditional(!F().S)) cycles += 6; } + void rm() { if (returnConditional(F() & SF)) cycles += 6; } + void rp() { if (returnConditional(!(F() & SF))) cycles += 6; } // restart @@ -594,49 +606,49 @@ namespace EightBit { void rlc() { auto carry = A() & Bit7; A() <<= 1; - A() |= carry >> 7; - F().C = carry != 0; + carry ? A() |= Bit0 : A() &= ~Bit0; + setFlag(CF, carry); } void rrc() { - auto carry = A() & 1; + auto carry = A() & Bit0; A() >>= 1; - A() |= carry << 7; - F().C = carry != 0; + carry ? A() |= Bit7 : A() &= ~Bit7; + setFlag(CF, carry); } void ral() { auto carry = A() & Bit7; A() <<= 1; - A() |= (uint8_t)F().C; - F().C = carry != 0; + A() |= (F() & CF); + setFlag(CF, carry); } void rar() { auto carry = A() & 1; A() >>= 1; - A() |= F().C << 7; - F().C = carry != 0; + A() |= (F() & CF) << 7; + setFlag(CF, carry); } // specials void cma() { A() ^= Mask8; } - void stc() { F().C = true; } - void cmc() { F().C = !F().C; } + void stc() { setFlag(CF); } + void cmc() { clearFlag(CF, F() & CF); } void daa() { - auto carry = F().C; + auto carry = F() & CF; uint8_t addition = 0; - if (F().AC || lowNibble(A()) > 9) { + if ((F() & AC) || lowNibble(A()) > 9) { addition = 0x6; } - if (F().C || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) { + if ((F() & CF) || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) { addition |= 0x60; carry = true; } add(addition); - F().C = carry; + setFlag(CF, carry); } // input/output diff --git a/Intel8080/inc/StatusFlags.h b/Intel8080/inc/StatusFlags.h deleted file mode 100644 index c9c05ec..0000000 --- a/Intel8080/inc/StatusFlags.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include - -namespace EightBit { - struct StatusFlags { - - bool S; - bool Z; - bool AC; - bool P; - bool C; - - enum StatusBits { - Sign = 0x80, // S - Zero = 0x40, // Z - AuxiliaryCarry = 0x10, // AC - Parity = 0x4, // Z - Carry = 0x1, // S - }; - - StatusFlags(uint8_t value) { - S = (value & StatusBits::Sign) != 0; - Z = (value & StatusBits::Zero) != 0; - AC = (value & StatusBits::AuxiliaryCarry) != 0; - P = (value & StatusBits::Parity) != 0; - C = (value & StatusBits::Carry) != 0; - } - - operator uint8_t() const { - - uint8_t flags = 0; - - if (S) - flags |= StatusBits::Sign; - - if (Z) - flags |= StatusBits::Zero; - - flags &= ~0x20; // Reserved off - - if (AC) - flags |= StatusBits::AuxiliaryCarry; - - flags &= ~0x8; // Reserved off - - if (P) - flags |= StatusBits::Parity; - - flags |= 0x2; // Reserved on - - if (C) - flags |= StatusBits::Carry; - - return flags; - } - - operator std::string() const { - std::string returned; - returned += S ? "S" : "-"; - returned += Z ? "Z" : "-"; - returned += "0"; - returned += AC ? "A" : "-"; - returned += "0"; - returned += P ? "P" : "-"; - returned += "1"; - returned += C ? "C" : "-"; - return returned; - } - }; -} \ No newline at end of file diff --git a/Intel8080/src/Disassembler.cpp b/Intel8080/src/Disassembler.cpp index 186c946..56d80cd 100644 --- a/Intel8080/src/Disassembler.cpp +++ b/Intel8080/src/Disassembler.cpp @@ -7,7 +7,6 @@ #include "Memory.h" #include "Intel8080.h" -#include "StatusFlags.h" EightBit::Disassembler::Disassembler() { } @@ -35,7 +34,7 @@ std::string EightBit::Disassembler::state(Intel8080& cpu) { << "PC=" << hex(pc.word) << " " << "SP=" << hex(sp.word) - << " " << "A=" << hex(a) << " " << "F=" << (std::string)f + << " " << "A=" << hex(a) << " " << "F=" << flags(f) << " " << "B=" << hex(b) << " " << "C=" << hex(c) << " " << "D=" << hex(d) << " " << "E=" << hex(e) << " " << "H=" << hex(h) << " " << "L=" << hex(l); @@ -87,6 +86,26 @@ std::string EightBit::Disassembler::disassemble(Intel8080& cpu) { return output.str(); } +std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) { + std::ostringstream output; + output << (value & flag ? represents : "-"); + return output.str(); +} + +std::string EightBit::Disassembler::flags(uint8_t value) { + std::ostringstream output; + output + << flag(value, Intel8080::SF, "S") + << flag(value, Intel8080::ZF, "Z") + << "0" + << flag(value, Intel8080::AC, "A") + << "0" + << flag(value, Intel8080::PF, "P") + << "1" + << flag(value, Intel8080::CF, "C"); + return output.str(); +} + std::string EightBit::Disassembler::hex(uint8_t value) { std::ostringstream output; output << std::hex << std::setw(2) << std::setfill('0') << (int)value; diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index e287b97..13f580f 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -5,11 +5,9 @@ #include "Disassembler.h" EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports) -: IntelProcessor(memory), - a(0), - f(0), - m_interrupt(false), - m_ports(ports) { +: IntelProcessor(memory), + m_interrupt(false), + m_ports(ports) { bc.word = de.word = hl.word = 0; installInstructions(); } @@ -61,8 +59,7 @@ void EightBit::Intel8080::installInstructions() { void EightBit::Intel8080::initialise() { Processor::initialise(); - bc.word = de.word = hl.word = 0; - a = f = 0; + AF().word = BC().word = DE().word = HL().word = 0; } int EightBit::Intel8080::step() { diff --git a/Intel8080/src/Intel8080.vcxproj b/Intel8080/src/Intel8080.vcxproj index 3e68f82..dcda7a7 100644 --- a/Intel8080/src/Intel8080.vcxproj +++ b/Intel8080/src/Intel8080.vcxproj @@ -148,7 +148,6 @@ - diff --git a/Intel8080/src/Intel8080.vcxproj.filters b/Intel8080/src/Intel8080.vcxproj.filters index 0f06fb3..567a441 100644 --- a/Intel8080/src/Intel8080.vcxproj.filters +++ b/Intel8080/src/Intel8080.vcxproj.filters @@ -29,9 +29,6 @@ Header Files - - Header Files -