diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h index 4d13213..8ec59de 100644 --- a/MC6809/inc/mc6809.h +++ b/MC6809/inc/mc6809.h @@ -12,26 +12,42 @@ 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. + + // 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. + EF = Bit7, + + // Fast interrupt mask: set if the FIRQ interrupt is disabled. + FF = Bit6, + + // Half carry: set if there was a carry from bit 3 to bit 4 of the result + // during the last add operation. + HF = Bit5, + + // Interrupt mask: set if the IRQ interrupt is disabled. + IF = Bit4, + + // 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. + NF = Bit3, + + // 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. + ZF = Bit2, + + // Overflow: set if there was an overflow during last result calculation. + // Logical, load and store operations clear this bit. + VF = Bit1, + + // 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. + CF = Bit0, }; mc6809(Bus& bus); @@ -71,131 +87,19 @@ namespace EightBit { const uint8_t SWI3vector = 0xf2; const uint8_t RESERVEDvector = 0xf0; - // + // Register selection for "indexed" + register16_t& RR(int which); - void Address_direct() { - BUS().ADDRESS() = register16_t(fetchByte(), DP()); - } + // Addressing modes + void Address_direct(); + void Address_indexed(); + void Address_extended(); - 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; - } - } - - void Address_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; - } - } - - void Address_extended() { - BUS().ADDRESS() = fetchWord(); - } - - // - - uint8_t AM_immediate() { - return fetchByte(); - } - - uint8_t AM_direct() { - Address_direct(); - return BUS().read(); - } - - uint8_t AM_indexed() { - Address_indexed(); - return BUS().read(); - } - - uint8_t AM_extended() { - Address_extended(); - return BUS().read(); - } - - // + // Addressing mode readers + uint8_t AM_immediate(); + uint8_t AM_direct(); + uint8_t AM_indexed(); + uint8_t AM_extended(); void abx(); uint8_t adc(uint8_t operand, uint8_t data); diff --git a/MC6809/src/mc6809.cpp b/MC6809/src/mc6809.cpp index 5531f1b..23c2a56 100644 --- a/MC6809/src/mc6809.cpp +++ b/MC6809/src/mc6809.cpp @@ -51,7 +51,7 @@ int EightBit::mc6809::execute(uint8_t cell) { case 0x70: addCycles(7); BUS().write(neg(AM_extended())); break; // NEG (extended) default: - ASSUME(false); + UNREACHABLE; } ASSUME(cycles() > 0); @@ -60,6 +60,126 @@ int EightBit::mc6809::execute(uint8_t cell) { // +EightBit::register16_t& EightBit::mc6809::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; + } +} + +void EightBit::mc6809::Address_direct() { + BUS().ADDRESS() = register16_t(fetchByte(), DP()); +} + +void EightBit::mc6809::Address_indexed() { + const auto type = fetchByte(); + auto& r = RR((type & (Bit6 | Bit5)) >> 5); + + if (type & Bit7) { + const auto indirect = type & Bit4; + switch (type & Mask4) { + case 0b0000: // ,R+ + ASSUME(!indirect); + addCycles(2); + BUS().ADDRESS() = r++; + break; + case 0b0001: // ,R++ + addCycles(3); + BUS().ADDRESS() = r; + r += 2; + break; + case 0b0010: // ,-R + ASSUME(!indirect); + addCycles(2); + BUS().ADDRESS() = --r; + break; + case 0b0011: // ,--R + addCycles(3); + r -= 2; + BUS().ADDRESS() = r; + break; + case 0b0100: // ,R + BUS().ADDRESS() = r; + break; + case 0b0101: // B,R + addCycles(1); + BUS().ADDRESS() = r + (int8_t)B(); + break; + case 0b0110: // A,R + addCycles(1); + BUS().ADDRESS() = r + (int8_t)A(); + break; + case 0b1000: // n,R (eight-bit) + addCycles(1); + BUS().ADDRESS() = r + (int8_t)fetchByte(); + break; + case 0b1001: // n,R (sixteen-bit) + addCycles(4); + BUS().ADDRESS() = r + (int16_t)fetchWord().word; + break; + case 0b1011: // D,R + addCycles(4); + BUS().ADDRESS() = r + 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: + UNREACHABLE; + } + if (indirect) { + addCycles(3); + BUS().ADDRESS() = fetchWord(); + } + } else { + // EA = ,R + 5-bit offset + addCycle(); + BUS().ADDRESS() = r + (type & Mask5); + } +} + +void EightBit::mc6809::Address_extended() { + BUS().ADDRESS() = fetchWord(); +} + +// + +uint8_t EightBit::mc6809::AM_immediate() { + return fetchByte(); +} + +uint8_t EightBit::mc6809::AM_direct() { + Address_direct(); + return BUS().read(); +} + +uint8_t EightBit::mc6809::AM_indexed() { + Address_indexed(); + return BUS().read(); +} + +uint8_t EightBit::mc6809::AM_extended() { + Address_extended(); + return BUS().read(); +} + +// + void EightBit::mc6809::abx() { X() += B(); }