Lots of reworking of the 6809 core, still looking for the FP bug.

This commit is contained in:
Adrian Conlon 2021-12-08 19:49:05 +00:00
parent 5522fde9a7
commit cea3fd47af
2 changed files with 136 additions and 143 deletions

View File

@ -66,21 +66,32 @@ namespace EightBit {
Signal<mc6809> ExecutingInstruction;
Signal<mc6809> ExecutedInstruction;
virtual int execute() final;
virtual int step() final;
int execute() final;
[[nodiscard]] int step() final;
auto& D() { return m_d; }
auto& A() { return D().high; }
auto& B() { return D().low; }
[[nodiscard]] constexpr auto& D() noexcept { return m_d; }
[[nodiscard]] constexpr auto& A() noexcept { return D().high; }
[[nodiscard]] constexpr auto& B() noexcept { return D().low; }
auto& X() { return m_x; }
auto& Y() { return m_y; }
auto& U() { return m_u; }
auto& S() { return m_s; }
[[nodiscard]] constexpr auto& X() noexcept { return m_x; }
[[nodiscard]] constexpr auto& Y() noexcept { return m_y; }
[[nodiscard]] constexpr auto& U() noexcept { return m_u; }
[[nodiscard]] constexpr auto& S() noexcept { return m_s; }
auto& DP() { return m_dp; }
auto& CC() { return m_cc; }
const auto& CC() const { return m_cc; }
[[nodiscard]] constexpr auto& DP() noexcept { return m_dp; }
[[nodiscard]] constexpr auto& CC() noexcept { return m_cc; }
[[nodiscard]] constexpr const auto& CC() const noexcept { return m_cc; }
// Flag checking
[[nodiscard]] constexpr auto fastInterruptMasked() const noexcept { return CC() & FF; }
[[nodiscard]] constexpr auto interruptMasked() const noexcept { return CC() & IF; }
[[nodiscard]] constexpr auto negative() const noexcept { return CC() & NF; }
[[nodiscard]] constexpr auto zero() const noexcept { return CC() & ZF; }
[[nodiscard]] constexpr auto overflow() const noexcept { return CC() & VF; }
[[nodiscard]] constexpr auto carry() const noexcept { return CC() & CF; }
[[nodiscard]] constexpr auto halfCarry() const noexcept { return CC() & HF; }
// |---------------|-----------------------------------|
// | MPU State | |
@ -100,21 +111,21 @@ namespace EightBit {
protected:
// Default push/pop handlers
virtual void push(uint8_t value) final;
virtual uint8_t pop() final;
void push(uint8_t value) final;
[[nodiscard]] uint8_t pop() final;
// Interrupt (etc.) handlers
virtual void handleRESET() final;
virtual void handleINT() final;
void handleRESET() final;
void handleINT() final;
// Bus reader/writers
virtual void busWrite() final;
virtual uint8_t busRead() final;
void busWrite() final;
uint8_t busRead() final;
virtual void call(register16_t destination) final;
virtual void ret() final;
void call(register16_t destination) final;
void ret() final;
private:
const uint8_t RESETvector = 0xfe; // RESET vector
@ -164,18 +175,18 @@ namespace EightBit {
void pushWordS(const register16_t value) { pushWord(S(), value); }
void pushWordU(const register16_t value) { pushWord(U(), value); }
uint8_t pop(register16_t& stack);
uint8_t popS() { return pop(S()); }
uint8_t popU() { return pop(U()); }
[[nodiscard]] uint8_t pop(register16_t& stack);
[[nodiscard]] uint8_t popS() { return pop(S()); }
[[nodiscard]] uint8_t popU() { return pop(U()); }
register16_t popWord(register16_t& stack) {
[[nodiscard]] register16_t popWord(register16_t& stack) {
const auto high = pop(stack);
const auto low = pop(stack);
return register16_t(low, high);
}
auto popWordS() { return popWord(S()); }
auto popWordU() { return popWord(U()); }
[[nodiscard]] auto popWordS() { return popWord(S()); }
[[nodiscard]] auto popWordU() { return popWord(U()); }
// Interrupt (etc.) handlers
@ -190,80 +201,80 @@ namespace EightBit {
void execute11();
// Register selection for "indexed"
register16_t& RR(int which);
[[nodiscard]] register16_t& RR(int which);
// Register selection for 8-bit transfer/exchange
uint8_t& referenceTransfer8(int specifier);
[[nodiscard]] uint8_t& referenceTransfer8(int specifier) noexcept;
// Register selection for 16-bit transfer/exchange
register16_t& referenceTransfer16(int specifier);
[[nodiscard]] register16_t& referenceTransfer16(int specifier);
// Addressing modes
register16_t Address_direct(); // DP + fetched offset
register16_t Address_indexed(); // Indexed address, complicated!
register16_t Address_extended(); // Fetched address
register16_t Address_relative_byte(); // PC + fetched byte offset
register16_t Address_relative_word(); // PC + fetched word offset
[[nodiscard]] register16_t Address_direct(); // DP + fetched offset
[[nodiscard]] register16_t Address_indexed(); // Indexed address, complicated!
[[nodiscard]] register16_t Address_extended(); // Fetched address
register16_t Address_relative_byte(); // PC + fetched byte offset
register16_t Address_relative_word(); // PC + fetched word offset
// Addressing mode readers
// Single byte readers
uint8_t AM_immediate_byte();
uint8_t AM_direct_byte();
uint8_t AM_indexed_byte();
uint8_t AM_extended_byte();
[[nodiscard]] uint8_t AM_immediate_byte();
[[nodiscard]] uint8_t AM_direct_byte();
[[nodiscard]] uint8_t AM_indexed_byte();
[[nodiscard]] uint8_t AM_extended_byte();
// Word readers
register16_t AM_immediate_word();
register16_t AM_direct_word();
register16_t AM_indexed_word();
register16_t AM_extended_word();
[[nodiscard]] register16_t AM_immediate_word();
[[nodiscard]] register16_t AM_direct_word();
[[nodiscard]] register16_t AM_indexed_word();
[[nodiscard]] register16_t AM_extended_word();
// Flag adjustment
template<class T> void adjustZero(const T datum) { CC() = clearBit(CC(), ZF, datum); }
void adjustZero(const register16_t datum) { CC() = clearBit(CC(), ZF, datum.word); }
void adjustNegative(const uint8_t datum) { CC() = setBit(CC(), NF, datum & Bit7); }
void adjustNegative(const uint16_t datum) { CC() = setBit(CC(), NF, datum & Bit15); }
void adjustNegative(const register16_t datum) { adjustNegative(datum.word); }
template<class T> constexpr void adjustZero(const T datum) noexcept { CC() = clearBit(CC(), ZF, datum); }
constexpr void adjustZero(const register16_t datum) noexcept { CC() = clearBit(CC(), ZF, datum.word); }
constexpr void adjustNegative(const uint8_t datum) noexcept { CC() = setBit(CC(), NF, datum & Bit7); }
constexpr void adjustNegative(const register16_t datum) noexcept { adjustNegative(datum.high); }
constexpr void adjustNegative(const uint16_t datum) noexcept { adjustNegative(register16_t(datum)); }
template<class T> void adjustNZ(const T datum) {
template<class T> constexpr void adjustNZ(const T datum) noexcept {
adjustZero(datum);
adjustNegative(datum);
}
void adjustCarry(const uint16_t datum) { CC() = setBit(CC(), CF, datum & Bit8); } // 8-bit addition
void adjustCarry(const uint32_t datum) { CC() = setBit(CC(), CF, datum & Bit16); } // 16-bit addition
void adjustCarry(const register16_t datum) { adjustCarry(datum.word); }
constexpr void adjustCarry(const uint16_t datum) noexcept { CC() = setBit(CC(), CF, datum & Bit8); } // 8-bit addition
constexpr void adjustCarry(const uint32_t datum) noexcept { CC() = setBit(CC(), CF, datum & Bit16); } // 16-bit addition
constexpr void adjustCarry(const register16_t datum) noexcept { adjustCarry(datum.word); }
void adjustBorrow(const uint16_t datum) { CC() = clearBit(CC(), CF, datum & Bit8); } // 8-bit subtraction
void adjustBorrow(const uint32_t datum) { CC() = clearBit(CC(), CF, datum & Bit16); } // 16-bit subtraction
void adjustBorrow(const register16_t datum) { adjustBorrow(datum.word); }
constexpr void adjustBorrow(const uint16_t datum) noexcept { CC() = clearBit(CC(), CF, datum & Bit8); } // 8-bit subtraction
constexpr void adjustBorrow(const uint32_t datum) noexcept { CC() = clearBit(CC(), CF, datum & Bit16); } // 16-bit subtraction
constexpr void adjustBorrow(const register16_t datum) noexcept { adjustBorrow(datum.word); }
void adjustOverflow(const uint8_t before, const uint8_t data, const register16_t after) {
constexpr void adjustOverflow(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
const uint8_t lowAfter = after.low;
const uint8_t highAfter = after.high;
CC() = setBit(CC(), VF, (before ^ data ^ lowAfter ^ (highAfter << 7)) & Bit7);
}
void adjustOverflow(const uint16_t before, const uint16_t data, const uint32_t after) {
constexpr void adjustOverflow(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
const uint16_t lowAfter = after & Mask16;
const uint16_t highAfter = after >> 16;
CC() = setBit(CC(), VF, (before ^ data ^ lowAfter ^ (highAfter << 15)) & Bit15);
}
void adjustOverflow(const register16_t before, const register16_t data, const register16_t after) {
constexpr void adjustOverflow(const register16_t before, const register16_t data, const register16_t after) noexcept {
adjustOverflow(before.word, data.word, after.word);
}
void adjustHalfCarry(const uint8_t before, const uint8_t data, const uint8_t after) {
constexpr void adjustHalfCarry(const uint8_t before, const uint8_t data, const uint8_t after) noexcept {
CC() = setBit(CC(), HF, (before ^ data ^ after) & Bit4);
}
void adjustAddition(const uint8_t before, const uint8_t data, const register16_t after) {
constexpr void adjustAddition(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
const auto result = after.low;
adjustNZ(result);
adjustCarry(after);
@ -271,62 +282,52 @@ namespace EightBit {
adjustHalfCarry(before, data, result);
}
void adjustAddition(const uint16_t before, const uint16_t data, const uint32_t after) {
constexpr void adjustAddition(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
const register16_t result = after & Mask16;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
void adjustAddition(const register16_t before, const register16_t data, const uint32_t after) {
constexpr void adjustAddition(const register16_t before, const register16_t data, const uint32_t after) noexcept {
adjustAddition(before.word, data.word, after);
}
void adjustSubtraction(const uint8_t before, const uint8_t data, const register16_t after) {
constexpr void adjustSubtraction(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
const auto result = after.low;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
void adjustSubtraction(const uint16_t before, const uint16_t data, const uint32_t after) {
constexpr void adjustSubtraction(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
const register16_t result = after & Mask16;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
void adjustSubtraction(const register16_t before, const register16_t data, const uint32_t after) {
constexpr void adjustSubtraction(const register16_t before, const register16_t data, const uint32_t after) noexcept {
adjustSubtraction(before.word, data.word, after);
}
// Flag checking
auto fastInterruptMasked() const { return CC() & FF; }
auto interruptMasked() const { return CC() & IF; }
auto negative() const { return CC() & NF; }
auto zero() const { return CC() & ZF; }
auto overflow() const { return CC() & VF; }
auto carry() const { return CC() & CF; }
auto halfCarry() const { return CC() & HF; }
auto LS() const { return carry() || zero(); } // (C OR Z)
auto HI() const { return !LS(); } // !(C OR Z)
auto LT() const { return (negative() >> 3) ^ (overflow() >> 1); } // (N XOR V)
auto GE() const { return !LT(); } // !(N XOR V)
auto LE() const { return zero() || LT(); } // (Z OR (N XOR V))
auto GT() const { return !LE(); } // !(Z OR (N XOR V))
[[nodiscard]] constexpr auto LS() const noexcept { return carry() || zero(); } // (C OR Z)
[[nodiscard]] constexpr auto HI() const noexcept { return !LS(); } // !(C OR Z)
[[nodiscard]] constexpr auto LT() const noexcept { return (negative() >> 3) ^ (overflow() >> 1); } // (N XOR V)
[[nodiscard]] constexpr auto GE() const noexcept { return !LT(); } // !(N XOR V)
[[nodiscard]] constexpr auto LE() const noexcept { return zero() || LT(); } // (Z OR (N XOR V))
[[nodiscard]] constexpr auto GT() const noexcept { return !LE(); } // !(Z OR (N XOR V))
// Branching
auto branch(const register16_t destination, const bool condition) {
auto branch(const register16_t destination, const bool condition) noexcept {
if (condition)
jump(destination);
return condition;
}
void branchShort(const bool condition) {
void branchShort(const bool condition) noexcept {
branch(Address_relative_byte(), condition);
}
@ -342,7 +343,7 @@ namespace EightBit {
void saveRegisterState();
void restoreRegisterState();
template <class T> T through(const T data) {
template <class T> constexpr T through(const T data) noexcept {
CC() = clearBit(CC(), VF);
adjustNZ(data);
return data;
@ -350,14 +351,6 @@ namespace EightBit {
// Instruction implementations
template <class T> T ld(const T data) {
return through(data);
}
template <class T> T st(const T data) {
return through(data);
}
uint8_t adc(uint8_t operand, uint8_t data);
uint8_t add(uint8_t operand, uint8_t data, uint8_t carry = 0);
register16_t add(register16_t operand, register16_t data);
@ -372,7 +365,7 @@ namespace EightBit {
void cwai(uint8_t data);
uint8_t da(uint8_t operand);
uint8_t dec(uint8_t operand);
uint8_t eorr(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data) noexcept;
void exg(uint8_t data);
uint8_t inc(uint8_t operand);
void jsr(register16_t address);

View File

@ -318,34 +318,34 @@ void EightBit::mc6809::executeUnprefixed() {
// LD
// LDA
case 0x86: A() = ld(AM_immediate_byte()); break; // LD (LDA immediate)
case 0x96: A() = ld(AM_direct_byte()); break; // LD (LDA direct)
case 0xa6: A() = ld(AM_indexed_byte()); break; // LD (LDA indexed)
case 0xb6: A() = ld(AM_extended_byte()); break; // LD (LDA extended)
case 0x86: A() = through(AM_immediate_byte()); break; // LD (LDA immediate)
case 0x96: A() = through(AM_direct_byte()); break; // LD (LDA direct)
case 0xa6: A() = through(AM_indexed_byte()); break; // LD (LDA indexed)
case 0xb6: A() = through(AM_extended_byte()); break; // LD (LDA extended)
// LDB
case 0xc6: B() = ld(AM_immediate_byte()); break; // LD (LDB immediate)
case 0xd6: B() = ld(AM_direct_byte()); break; // LD (LDB direct)
case 0xe6: B() = ld(AM_indexed_byte()); break; // LD (LDB indexed)
case 0xf6: B() = ld(AM_extended_byte()); break; // LD (LDB extended)
case 0xc6: B() = through(AM_immediate_byte()); break; // LD (LDB immediate)
case 0xd6: B() = through(AM_direct_byte()); break; // LD (LDB direct)
case 0xe6: B() = through(AM_indexed_byte()); break; // LD (LDB indexed)
case 0xf6: B() = through(AM_extended_byte()); break; // LD (LDB extended)
// LDD
case 0xcc: D() = ld(AM_immediate_word()); break; // LD (LDD immediate)
case 0xdc: D() = ld(AM_direct_word()); break; // LD (LDD direct)
case 0xec: D() = ld(AM_indexed_word()); break; // LD (LDD indexed)
case 0xfc: D() = ld(AM_extended_word()); break; // LD (LDD extended)
case 0xcc: D() = through(AM_immediate_word()); break; // LD (LDD immediate)
case 0xdc: D() = through(AM_direct_word()); break; // LD (LDD direct)
case 0xec: D() = through(AM_indexed_word()); break; // LD (LDD indexed)
case 0xfc: D() = through(AM_extended_word()); break; // LD (LDD extended)
// LDU
case 0xce: U() = ld(AM_immediate_word()); break; // LD (LDU immediate)
case 0xde: U() = ld(AM_direct_word()); break; // LD (LDU direct)
case 0xee: U() = ld(AM_indexed_word()); break; // LD (LDU indexed)
case 0xfe: U() = ld(AM_extended_word()); break; // LD (LDU extended)
case 0xce: U() = through(AM_immediate_word()); break; // LD (LDU immediate)
case 0xde: U() = through(AM_direct_word()); break; // LD (LDU direct)
case 0xee: U() = through(AM_indexed_word()); break; // LD (LDU indexed)
case 0xfe: U() = through(AM_extended_word()); break; // LD (LDU extended)
// LDX
case 0x8e: X() = ld(AM_immediate_word()); break; // LD (LDX immediate)
case 0x9e: X() = ld(AM_direct_word()); break; // LD (LDX direct)
case 0xae: X() = ld(AM_indexed_word()); break; // LD (LDX indexed)
case 0xbe: X() = ld(AM_extended_word()); break; // LD (LDX extended)
case 0x8e: X() = through(AM_immediate_word()); break; // LD (LDX immediate)
case 0x9e: X() = through(AM_direct_word()); break; // LD (LDX direct)
case 0xae: X() = through(AM_indexed_word()); break; // LD (LDX indexed)
case 0xbe: X() = through(AM_extended_word()); break; // LD (LDX extended)
// LEA
case 0x30: adjustZero(X() = Address_indexed()); break; // LEA (LEAX indexed)
@ -438,29 +438,29 @@ void EightBit::mc6809::executeUnprefixed() {
// ST
// STA
case 0x97: memoryWrite(Address_direct(), st(A())); break; // ST (STA direct)
case 0xa7: memoryWrite(Address_indexed(), st(A())); break; // ST (STA indexed)
case 0xb7: memoryWrite(Address_extended(), st(A())); break; // ST (STA extended)
case 0x97: memoryWrite(Address_direct(), through(A())); break; // ST (STA direct)
case 0xa7: memoryWrite(Address_indexed(), through(A())); break; // ST (STA indexed)
case 0xb7: memoryWrite(Address_extended(), through(A())); break; // ST (STA extended)
// STB
case 0xd7: memoryWrite(Address_direct(), st(B())); break; // ST (STB direct)
case 0xe7: memoryWrite(Address_indexed(), st(B())); break; // ST (STB indexed)
case 0xf7: memoryWrite(Address_extended(), st(B())); break; // ST (STB extended)
case 0xd7: memoryWrite(Address_direct(), through(B())); break; // ST (STB direct)
case 0xe7: memoryWrite(Address_indexed(), through(B())); break; // ST (STB indexed)
case 0xf7: memoryWrite(Address_extended(), through(B())); break; // ST (STB extended)
// STD
case 0xdd: Processor::setWord(Address_direct(), st(D())); break; // ST (STD direct)
case 0xed: Processor::setWord(Address_indexed(), st(D())); break; // ST (STD indexed)
case 0xfd: Processor::setWord(Address_extended(), st(D())); break; // ST (STD extended)
case 0xdd: Processor::setWord(Address_direct(), through(D())); break; // ST (STD direct)
case 0xed: Processor::setWord(Address_indexed(), through(D())); break; // ST (STD indexed)
case 0xfd: Processor::setWord(Address_extended(), through(D())); break; // ST (STD extended)
// STU
case 0xdf: Processor::setWord(Address_direct(), st(U())); break; // ST (STU direct)
case 0xef: Processor::setWord(Address_indexed(), st(U())); break; // ST (STU indexed)
case 0xff: Processor::setWord(Address_extended(), st(U())); break; // ST (STU extended)
case 0xdf: Processor::setWord(Address_direct(), through(U())); break; // ST (STU direct)
case 0xef: Processor::setWord(Address_indexed(), through(U())); break; // ST (STU indexed)
case 0xff: Processor::setWord(Address_extended(), through(U())); break; // ST (STU extended)
// STX
case 0x9f: Processor::setWord(Address_direct(), st(X())); break; // ST (STX direct)
case 0xaf: Processor::setWord(Address_indexed(), st(X())); break; // ST (STX indexed)
case 0xbf: Processor::setWord(Address_extended(), st(X())); break; // ST (STX extended)
case 0x9f: Processor::setWord(Address_direct(), through(X())); break; // ST (STX direct)
case 0xaf: Processor::setWord(Address_indexed(), through(X())); break; // ST (STX indexed)
case 0xbf: Processor::setWord(Address_extended(), through(X())); break; // ST (STX extended)
// SUB
@ -550,16 +550,16 @@ void EightBit::mc6809::execute10() {
// LD
// LDS
case 0xce: S() = ld(AM_immediate_word()); break; // LD (LDS immediate)
case 0xde: S() = ld(AM_direct_word()); break; // LD (LDS direct)
case 0xee: S() = ld(AM_indexed_word()); break; // LD (LDS indexed)
case 0xfe: S() = ld(AM_extended_word()); break; // LD (LDS extended)
case 0xce: S() = through(AM_immediate_word()); break; // LD (LDS immediate)
case 0xde: S() = through(AM_direct_word()); break; // LD (LDS direct)
case 0xee: S() = through(AM_indexed_word()); break; // LD (LDS indexed)
case 0xfe: S() = through(AM_extended_word()); break; // LD (LDS extended)
// LDY
case 0x8e: Y() = ld(AM_immediate_word()); break; // LD (LDY immediate)
case 0x9e: Y() = ld(AM_direct_word()); break; // LD (LDY direct)
case 0xae: Y() = ld(AM_indexed_word()); break; // LD (LDY indexed)
case 0xbe: Y() = ld(AM_extended_word()); break; // LD (LDY extended)
case 0x8e: Y() = through(AM_immediate_word()); break; // LD (LDY immediate)
case 0x9e: Y() = through(AM_direct_word()); break; // LD (LDY direct)
case 0xae: Y() = through(AM_indexed_word()); break; // LD (LDY indexed)
case 0xbe: Y() = through(AM_extended_word()); break; // LD (LDY extended)
// Branching
@ -580,14 +580,14 @@ void EightBit::mc6809::execute10() {
case 0x2f: branchLong(LE()); break; // BLE (LBLE relative)
// STS
case 0xdf: Processor::setWord(Address_direct(), st(S())); break; // ST (STS direct)
case 0xef: Processor::setWord(Address_indexed(), st(S())); break; // ST (STS indexed)
case 0xff: Processor::setWord(Address_extended(), st(S())); break; // ST (STS extended)
case 0xdf: Processor::setWord(Address_direct(), through(S())); break; // ST (STS direct)
case 0xef: Processor::setWord(Address_indexed(), through(S())); break; // ST (STS indexed)
case 0xff: Processor::setWord(Address_extended(), through(S())); break; // ST (STS extended)
// STY
case 0x9f: Processor::setWord(Address_direct(), st(Y())); break; // ST (STY direct)
case 0xaf: Processor::setWord(Address_indexed(), st(Y())); break; // ST (STY indexed)
case 0xbf: Processor::setWord(Address_extended(), st(Y())); break; // ST (STY extended)
case 0x9f: Processor::setWord(Address_direct(), through(Y())); break; // ST (STY direct)
case 0xaf: Processor::setWord(Address_indexed(), through(Y())); break; // ST (STY indexed)
case 0xbf: Processor::setWord(Address_extended(), through(Y())); break; // ST (STY extended)
// SWI
case 0x3f: memoryRead(); swi2(); break; // SWI (SWI2 inherent)
@ -923,11 +923,11 @@ uint8_t EightBit::mc6809::dec(const uint8_t operand) {
return result;
}
uint8_t EightBit::mc6809::eorr(const uint8_t operand, const uint8_t data) {
uint8_t EightBit::mc6809::eorr(const uint8_t operand, const uint8_t data) noexcept {
return through((uint8_t)(operand ^ data));
}
uint8_t& EightBit::mc6809::referenceTransfer8(const int specifier) {
uint8_t& EightBit::mc6809::referenceTransfer8(const int specifier) noexcept {
switch (specifier) {
case 0b1000:
return A();