diff --git a/EightBit.sln b/EightBit.sln index f2963ce..d9fc117 100644 --- a/EightBit.sln +++ b/EightBit.sln @@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ricoh2A03", "Ricoh2A03\src\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_M6502", "M6502\test\test_M6502.vcxproj", "{EF6F5840-328E-465A-A78A-E807BC9AEB4C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC6809", "MC6809\src\MC6809.vcxproj", "{09C1B50E-408E-48B1-A616-8400904B5829}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -121,6 +123,14 @@ Global {EF6F5840-328E-465A-A78A-E807BC9AEB4C}.Release|x64.Build.0 = Release|x64 {EF6F5840-328E-465A-A78A-E807BC9AEB4C}.Release|x86.ActiveCfg = Release|Win32 {EF6F5840-328E-465A-A78A-E807BC9AEB4C}.Release|x86.Build.0 = Release|Win32 + {09C1B50E-408E-48B1-A616-8400904B5829}.Debug|x64.ActiveCfg = Debug|x64 + {09C1B50E-408E-48B1-A616-8400904B5829}.Debug|x64.Build.0 = Debug|x64 + {09C1B50E-408E-48B1-A616-8400904B5829}.Debug|x86.ActiveCfg = Debug|Win32 + {09C1B50E-408E-48B1-A616-8400904B5829}.Debug|x86.Build.0 = Debug|Win32 + {09C1B50E-408E-48B1-A616-8400904B5829}.Release|x64.ActiveCfg = Release|x64 + {09C1B50E-408E-48B1-A616-8400904B5829}.Release|x64.Build.0 = Release|x64 + {09C1B50E-408E-48B1-A616-8400904B5829}.Release|x86.ActiveCfg = Release|Win32 + {09C1B50E-408E-48B1-A616-8400904B5829}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MC6809/documentation/6809 Assembly Language Programming - Leventhal.pdf b/MC6809/documentation/6809 Assembly Language Programming - Leventhal.pdf new file mode 100644 index 0000000..53b1cda Binary files /dev/null and b/MC6809/documentation/6809 Assembly Language Programming - Leventhal.pdf differ diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h new file mode 100644 index 0000000..13d2f39 --- /dev/null +++ b/MC6809/inc/mc6809.h @@ -0,0 +1,192 @@ +#pragma once + +// Uses some information from: +// http://www.cpu-world.com/Arch/6809.html + +#include + +#include +#include + +namespace EightBit { + class mc6809 : public BigEndianProcessor { + public: + enum StatusBits { + EF = Bit7, // Entire flag: set if the complete machine state was saved in the stack. + // If this bit is not set then only program counter and condition code + // registers were saved in the stack. This bit is used by interrupt + // handling routines only. + // The bit is cleared by fast interrupts, and set by all other interrupts. + FF = Bit6, // Fast interrupt mask: set if the FIRQ interrupt is disabled. + HF = Bit5, // Half carry: set if there was a carry from bit 3 to bit 4 of the result + // during the last add operation. + IF = Bit4, // Interrupt mask: set if the IRQ interrupt is disabled. + NF = Bit3, // Negative: set if the most significant bit of the result is set. + // This bit can be set not only by arithmetic and logical operations, + // but also by load / store operations. + ZF = Bit2, // Zero: set if the result is zero. Like the N bit, this bit can be + // set not only by arithmetic and logical operations, but also + // by load / store operations. + VF = Bit1, // Overflow: set if there was an overflow during last result calculation. + // Logical, load and store operations clear this bit. + CF = Bit0, // Carry: set if there was a carry from the bit 7 during last add + // operation, or if there was a borrow from last subtract operation, + // or if bit 7 of the A register was set during last MUL operation. + }; + + mc6809(Bus& bus); + + Signal ExecutingInstruction; + Signal ExecutedInstruction; + + virtual int execute(uint8_t opcode) final; + virtual int step() final; + virtual void powerOn() final; + + register16_t& D() { return m_d; } + uint8_t& A() { return D().high; } + uint8_t& B() { return D().low; } + + register16_t& X() { return m_x; } + register16_t& Y() { return m_y; } + register16_t& U() { return m_u; } + register16_t& S() { return m_s; } + + uint8_t& DP() { return m_dp; } + uint8_t& CC() { return m_cc; } + + PinLevel& IRQ() { return INT(); } + PinLevel& FIRQ() { return m_firq; } + + protected: + virtual void reset() final; + + private: + const uint8_t RESETvector = 0xfe; + const uint8_t NMIvector = 0xfc; + const uint8_t SWIvector = 0xfa; + const uint8_t IRQvector = 0xf8; + const uint8_t FIRQvector = 0xf6; + const uint8_t SWI2vector = 0xf4; + const uint8_t SWI3vector = 0xf2; + const uint8_t RESERVEDvector = 0xf0; + + uint8_t& AM_direct() { + BUS().ADDRESS() = register16_t(fetchByte(), DP()); + return BUS().reference(); + } + + register16_t& RR(int which) { + ASSUME(which >= 0); + ASSUME(which <= 3); + switch (which) { + case 0b00: + return X(); + case 0b01: + return Y(); + case 0b10: + return U(); + case 0b11: + return S(); + default: + UNREACHABLE; + } + } + + uint8_t& AM_indexed() { + const auto type = fetchByte(); + auto& rr = RR(type & (Bit6 | Bit5)); + switch (type & Bit7) { + case 0: // EA = ,R + 5-bit offset + addCycle(); + BUS().ADDRESS() = rr + (type & Mask5); + break; + case Bit7: { + const auto indirect = type & Bit4; + switch (type & Mask4) { + case 0b0000: // , R+ + ASSUME(!indirect); + addCycles(2); + BUS().ADDRESS() = rr++; + break; + case 0b0001: // , R++ + addCycles(3); + BUS().ADDRESS() = rr; + rr += 2; + break; + case 0b0010: // , -R + ASSUME(!indirect); + addCycles(2); + BUS().ADDRESS() = --rr; + break; + case 0b0011: // , --R + addCycles(3); + rr -= 2; + BUS().ADDRESS() = rr; + break; + case 0b0100: // , R + BUS().ADDRESS() = rr; + break; + case 0b0101: // B, R + addCycles(1); + BUS().ADDRESS() = rr + (int8_t)B(); + break; + case 0b0110: // A, R + addCycles(1); + BUS().ADDRESS() = rr + (int8_t)A(); + break; + case 0b1000: // n, R (eight-bit) + addCycles(1); + BUS().ADDRESS() = rr + (int8_t)fetchByte(); + break; + case 0b1001: // n, R (sixteen-bit) + addCycles(4); + BUS().ADDRESS() = rr + fetchWord(); + break; + case 0b1011: // D, R + addCycles(4); + BUS().ADDRESS() = rr + D(); + break; + case 0b1100: // n, PCR (eight-bit) + addCycles(1); + BUS().ADDRESS() = PC() + (int8_t)fetchByte(); + break; + case 0b1101: // n, PCR (sixteen-bit) + addCycles(1); + BUS().ADDRESS() = PC() + (int16_t)fetchWord().word; + break; + default: + ASSUME(false); + } + if (indirect) { + addCycles(3); + BUS().ADDRESS() = fetchWord(); + } + } + break; + default: + UNREACHABLE; + } + return BUS().reference(); + } + + uint8_t& AM_extended() { + BUS().ADDRESS() = fetchWord(); + return BUS().reference(); + } + + void abx(); + void neg(uint8_t& operand); + + register16_t m_d; + register16_t m_x; + register16_t m_y; + register16_t m_u; + register16_t m_s; + + uint8_t m_dp; + uint8_t m_cc; + + PinLevel m_firq; + }; +} \ No newline at end of file diff --git a/MC6809/inc/stdafx.h b/MC6809/inc/stdafx.h new file mode 100644 index 0000000..bf45a08 Binary files /dev/null and b/MC6809/inc/stdafx.h differ diff --git a/MC6809/src/MC6809.vcxproj b/MC6809/src/MC6809.vcxproj new file mode 100644 index 0000000..73b49eb --- /dev/null +++ b/MC6809/src/MC6809.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + Create + Create + Create + Create + + + + 15.0 + {09C1B50E-408E-48B1-A616-8400904B5829} + Win32Proj + MC6809 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + ..\inc;..\..\inc;C:\Libraries\boost_1_65_1;$(IncludePath) + + + true + ..\inc;..\..\inc;C:\Libraries\boost_1_65_1;$(IncludePath) + + + true + ..\inc;..\..\inc;C:\Libraries\boost_1_65_1;$(IncludePath) + + + false + ..\inc;..\..\inc;C:\Libraries\boost_1_65_1;$(IncludePath) + + + + Use + Level3 + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + AdvancedVectorExtensions + false + true + stdcpp17 + + + Windows + true + true + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + stdcpp17 + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + stdcpp17 + + + Windows + true + + + + + Use + Level3 + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + AdvancedVectorExtensions + false + true + stdcpp17 + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/MC6809/src/MC6809.vcxproj.filters b/MC6809/src/MC6809.vcxproj.filters new file mode 100644 index 0000000..7a6a495 --- /dev/null +++ b/MC6809/src/MC6809.vcxproj.filters @@ -0,0 +1,29 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/MC6809/src/mc6809.cpp b/MC6809/src/mc6809.cpp new file mode 100644 index 0000000..4374e79 --- /dev/null +++ b/MC6809/src/mc6809.cpp @@ -0,0 +1,64 @@ +#include "stdafx.h" +#include "mc6809.h" + +EightBit::mc6809::mc6809(Bus& bus) +: BigEndianProcessor(bus) {} + +void EightBit::mc6809::powerOn() { + Processor::powerOn(); +} + +int EightBit::mc6809::step() { + resetCycles(); + auto returned = 0; + if (LIKELY(powered())) { + ExecutingInstruction.fire(*this); + returned = execute(fetchByte()); + ExecutedInstruction.fire(*this); + } + return returned; +} + +void EightBit::mc6809::reset() { + Processor::reset(); + DP() = 0; // Reestablish zero page + CC() |= (IF & FF); // Disable interrupts + jump(getWordPaged(0xff, RESETvector)); +} + +int EightBit::mc6809::execute(uint8_t cell) { + + switch (cell) { + + // ABX + case 0x3a: addCycles(3); abx(); break; // ABX (inherent) + + // NEG + case 0x00: addCycles(6); neg(AM_direct()); break; // NEG (direct) + case 0x40: addCycles(2); neg(A()); break; // NEG (NEGA, inherent) + case 0x50: addCycles(2); neg(B()); break; // NEG (NEGB, inherent) + case 0x60: addCycles(6); neg(AM_indexed()); break; // NEG (indexed) + case 0x70: addCycles(7); neg(AM_extended()); break; // NEG (extended) + + default: + ASSUME(false); + } + + ASSUME(cycles() > 0); + return cycles(); +} + +// + +void EightBit::mc6809::abx() { + X() += B(); +} + +void EightBit::mc6809::neg(uint8_t& operand) { + setFlag(CC(), VF, operand == Bit7); + const register16_t result = 0 - operand; + operand = result.low; + setFlag(CC(), NF, operand & Bit7); + setFlag(CC(), ZF, operand == 0); + setFlag(CC(), CF, result.word & Bit8); +} \ No newline at end of file diff --git a/MC6809/src/stdafx.cpp b/MC6809/src/stdafx.cpp new file mode 100644 index 0000000..08343af Binary files /dev/null and b/MC6809/src/stdafx.cpp differ diff --git a/inc/Bus.h b/inc/Bus.h index 9ee8f56..e613a77 100644 --- a/inc/Bus.h +++ b/inc/Bus.h @@ -43,7 +43,6 @@ namespace EightBit { write(value); } - protected: virtual uint8_t& reference(uint16_t address) = 0; uint8_t& reference() { return reference(ADDRESS().word); }