diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h index 8c24dbd..f11ad49 100644 --- a/MC6809/inc/mc6809.h +++ b/MC6809/inc/mc6809.h @@ -111,6 +111,8 @@ namespace EightBit { virtual void busWrite() final; virtual uint8_t busRead() final; + virtual void call(register16_t destination) final; + private: const uint8_t RESETvector = 0xfe; // RESET vector const uint8_t NMIvector = 0xfc; // NMI vector @@ -303,7 +305,7 @@ namespace EightBit { void branchLong(const int condition) { if (branch(Address_relative_word(), condition)) - tick(); + memoryRead(0xffff); } // Miscellaneous @@ -336,7 +338,7 @@ namespace EightBit { uint8_t asl(uint8_t operand); uint8_t asr(uint8_t operand); void bit(uint8_t operand, uint8_t data); - uint8_t clr(); + uint8_t clr(uint8_t data = 0); // In this form for Read/Modify/Write operations void cmp(uint8_t operand, uint8_t data); void cmp(register16_t operand, register16_t data); uint8_t com(uint8_t operand); diff --git a/MC6809/src/mc6809.cpp b/MC6809/src/mc6809.cpp index 34ce62a..113c90d 100644 --- a/MC6809/src/mc6809.cpp +++ b/MC6809/src/mc6809.cpp @@ -4,6 +4,16 @@ #include #include +// Read/Modify/Write +#define RMW(ACCESSOR, OPERATION) \ +{ \ + const auto data = ACCESSOR(); \ + const auto address = BUS().ADDRESS(); \ + const auto result = OPERATION(data); \ + memoryRead(0xffff); \ + memoryWrite(address, result); \ +} + EightBit::mc6809::mc6809(Bus& bus) : BigEndianProcessor(bus) { RaisedPOWER.connect([this](EventArgs) { @@ -51,62 +61,89 @@ void EightBit::mc6809::handleHALT() { void EightBit::mc6809::handleRESET() { BigEndianProcessor::handleRESET(); + memoryRead(0xfffe); raiseNMI(); lowerBA(); raiseBS(); DP() = 0; CC() = setBit(CC(), IF); // Disable IRQ CC() = setBit(CC(), FF); // Disable FIRQ + memoryRead(0xfffe); + memoryRead(0xfffe); + memoryRead(0xfffe); jump(getWordPaged(0xff, RESETvector)); - tick(10); + memoryRead(0xffff); } void EightBit::mc6809::handleNMI() { raiseNMI(); lowerBA(); raiseBS(); + memoryRead(); + memoryRead(); + memoryRead(0xffff); saveEntireRegisterState(); + memoryRead(0xffff); CC() = setBit(CC(), IF); // Disable IRQ CC() = setBit(CC(), FF); // Disable FIRQ jump(getWordPaged(0xff, NMIvector)); - tick(12); + memoryRead(0xffff); } void EightBit::mc6809::handleINT() { BigEndianProcessor::handleINT(); lowerBA(); raiseBS(); + memoryRead(); + memoryRead(); + memoryRead(0xffff); saveEntireRegisterState(); + memoryRead(0xffff); CC() = setBit(CC(), IF); // Disable IRQ jump(getWordPaged(0xff, IRQvector)); - tick(12); + memoryRead(0xffff); } void EightBit::mc6809::handleFIRQ() { raiseFIRQ(); lowerBA(); raiseBS(); + memoryRead(); + memoryRead(); + memoryRead(0xffff); savePartialRegisterState(); + memoryRead(0xffff); CC() = setBit(CC(), IF); // Disable IRQ CC() = setBit(CC(), FF); // Disable FIRQ jump(getWordPaged(0xff, FIRQvector)); - tick(12); + memoryRead(0xffff); } // void EightBit::mc6809::busWrite() { + tick(); lowerRW(); Processor::busWrite(); } uint8_t EightBit::mc6809::busRead() { + tick(); raiseRW(); return Processor::busRead(); } // +void EightBit::mc6809::call(register16_t destination) { + memoryRead(destination); + memoryRead(0xffff); + BigEndianProcessor::pushWord(PC()); + jump(destination); +} + +// + int EightBit::mc6809::execute() { lowerBA(); lowerBS(); @@ -127,7 +164,7 @@ int EightBit::mc6809::execute() { void EightBit::mc6809::executeUnprefixed() { assert(!(m_prefix10 || m_prefix11)); - assert(cycles() == 0); + assert(cycles() == 1); // One fetch switch (opcode()) { @@ -135,359 +172,359 @@ void EightBit::mc6809::executeUnprefixed() { case 0x11: m_prefix11 = true; Processor::execute(fetchByte()); break; // ABX - case 0x3a: tick(3); X() += B(); break; // ABX (inherent) + case 0x3a: memoryRead(); X() += B(); memoryRead(0xffff); break; // ABX (inherent) // ADC - case 0x89: tick(2); A() = adc(A(), AM_immediate_byte()); break; // ADC (ADCA immediate) - case 0x99: tick(4); A() = adc(A(), AM_direct_byte()); break; // ADC (ADCA direct) - case 0xa9: tick(4); A() = adc(A(), AM_indexed_byte()); break; // ADC (ADCA indexed) - case 0xb9: tick(4); A() = adc(A(), AM_extended_byte()); break; // ADC (ADCA extended) + case 0x89: A() = adc(A(), AM_immediate_byte()); break; // ADC (ADCA immediate) + case 0x99: A() = adc(A(), AM_direct_byte()); break; // ADC (ADCA direct) + case 0xa9: A() = adc(A(), AM_indexed_byte()); break; // ADC (ADCA indexed) + case 0xb9: A() = adc(A(), AM_extended_byte()); break; // ADC (ADCA extended) - case 0xc9: tick(2); B() = adc(B(), AM_immediate_byte()); break; // ADC (ADCB immediate) - case 0xd9: tick(4); B() = adc(B(), AM_direct_byte()); break; // ADC (ADCB direct) - case 0xe9: tick(4); B() = adc(B(), AM_indexed_byte()); break; // ADC (ADCB indexed) - case 0xf9: tick(4); B() = adc(B(), AM_extended_byte()); break; // ADC (ADCB extended) + case 0xc9: B() = adc(B(), AM_immediate_byte()); break; // ADC (ADCB immediate) + case 0xd9: B() = adc(B(), AM_direct_byte()); break; // ADC (ADCB direct) + case 0xe9: B() = adc(B(), AM_indexed_byte()); break; // ADC (ADCB indexed) + case 0xf9: B() = adc(B(), AM_extended_byte()); break; // ADC (ADCB extended) // ADD - case 0x8b: tick(2); A() = add(A(), AM_immediate_byte()); break; // ADD (ADDA immediate) - case 0x9b: tick(4); A() = add(A(), AM_direct_byte()); break; // ADD (ADDA direct) - case 0xab: tick(4); A() = add(A(), AM_indexed_byte()); break; // ADD (ADDA indexed) - case 0xbb: tick(5); A() = add(A(), AM_extended_byte()); break; // ADD (ADDA extended) + case 0x8b: A() = add(A(), AM_immediate_byte()); break; // ADD (ADDA immediate) + case 0x9b: A() = add(A(), AM_direct_byte()); break; // ADD (ADDA direct) + case 0xab: A() = add(A(), AM_indexed_byte()); break; // ADD (ADDA indexed) + case 0xbb: A() = add(A(), AM_extended_byte()); break; // ADD (ADDA extended) - case 0xcb: tick(2); B() = add(B(), AM_immediate_byte()); break; // ADD (ADDB immediate) - case 0xdb: tick(4); B() = add(B(), AM_direct_byte()); break; // ADD (ADDB direct) - case 0xeb: tick(4); B() = add(B(), AM_indexed_byte()); break; // ADD (ADDB indexed) - case 0xfb: tick(5); B() = add(B(), AM_extended_byte()); break; // ADD (ADDB extended) + case 0xcb: B() = add(B(), AM_immediate_byte()); break; // ADD (ADDB immediate) + case 0xdb: B() = add(B(), AM_direct_byte()); break; // ADD (ADDB direct) + case 0xeb: B() = add(B(), AM_indexed_byte()); break; // ADD (ADDB indexed) + case 0xfb: B() = add(B(), AM_extended_byte()); break; // ADD (ADDB extended) - case 0xc3: tick(4); D() = add(D(), AM_immediate_word()); break; // ADD (ADDD immediate) - case 0xd3: tick(6); D() = add(D(), AM_direct_word()); break; // ADD (ADDD direct) - case 0xe3: tick(6); D() = add(D(), AM_indexed_word()); break; // ADD (ADDD indexed) - case 0xf3: tick(7); D() = add(D(), AM_extended_word()); break; // ADD (ADDD extended) + case 0xc3: D() = add(D(), AM_immediate_word()); break; // ADD (ADDD immediate) + case 0xd3: D() = add(D(), AM_direct_word()); break; // ADD (ADDD direct) + case 0xe3: D() = add(D(), AM_indexed_word()); break; // ADD (ADDD indexed) + case 0xf3: D() = add(D(), AM_extended_word()); break; // ADD (ADDD extended) // AND - case 0x84: tick(2); A() = andr(A(), AM_immediate_byte()); break; // AND (ANDA immediate) - case 0x94: tick(4); A() = andr(A(), AM_direct_byte()); break; // AND (ANDA direct) - case 0xa4: tick(4); A() = andr(A(), AM_indexed_byte()); break; // AND (ANDA indexed) - case 0xb4: tick(5); A() = andr(A(), AM_extended_byte()); break; // AND (ANDA extended) + case 0x84: A() = andr(A(), AM_immediate_byte()); break; // AND (ANDA immediate) + case 0x94: A() = andr(A(), AM_direct_byte()); break; // AND (ANDA direct) + case 0xa4: A() = andr(A(), AM_indexed_byte()); break; // AND (ANDA indexed) + case 0xb4: A() = andr(A(), AM_extended_byte()); break; // AND (ANDA extended) + + case 0xc4: B() = andr(B(), AM_immediate_byte()); break; // AND (ANDB immediate) + case 0xd4: B() = andr(B(), AM_direct_byte()); break; // AND (ANDB direct) + case 0xe4: B() = andr(B(), AM_indexed_byte()); break; // AND (ANDB indexed) + case 0xf4: B() = andr(B(), AM_extended_byte()); break; // AND (ANDB extended) - case 0xc4: tick(2); B() = andr(B(), AM_immediate_byte()); break; // AND (ANDB immediate) - case 0xd4: tick(4); B() = andr(B(), AM_direct_byte()); break; // AND (ANDB direct) - case 0xe4: tick(4); B() = andr(B(), AM_indexed_byte()); break; // AND (ANDB indexed) - case 0xf4: tick(5); B() = andr(B(), AM_extended_byte()); break; // AND (ANDB extended) - - case 0x1c: tick(3); CC() &= AM_immediate_byte(); break; // AND (ANDCC immediate) + case 0x1c: CC() &= AM_immediate_byte(); break; // AND (ANDCC immediate) // ASL/LSL - case 0x08: tick(6); memoryWrite(asl(AM_direct_byte())); break; // ASL (direct) - case 0x48: tick(2); A() = asl(A()); break; // ASL (ASLA inherent) - case 0x58: tick(2); B() = asl(B()); break; // ASL (ASLB inherent) - case 0x68: tick(6); memoryWrite(asl(AM_indexed_byte())); break; // ASL (indexed) - case 0x78: tick(7); memoryWrite(asl(AM_extended_byte())); break; // ASL (extended) + case 0x08: RMW(AM_direct_byte, asl); break; // ASL (direct) + case 0x48: memoryRead(); A() = asl(A()); break; // ASL (ASLA inherent) + case 0x58: memoryRead(); B() = asl(B()); break; // ASL (ASLB inherent) + case 0x68: RMW(AM_indexed_byte, asl); break; // ASL (indexed) + case 0x78: RMW(AM_extended_byte, asl); break; // ASL (extended) // ASR - case 0x07: tick(6); memoryWrite(asr(AM_direct_byte())); break; // ASR (direct) - case 0x47: tick(2); A() = asr(A()); break; // ASR (ASRA inherent) - case 0x57: tick(2); B() = asr(B()); break; // ASR (ASRB inherent) - case 0x67: tick(6); memoryWrite(asr(AM_indexed_byte())); break; // ASR (indexed) - case 0x77: tick(7); memoryWrite(asr(AM_extended_byte())); break; // ASR (extended) + case 0x07: RMW(AM_direct_byte, asr); break; // ASR (direct) + case 0x47: memoryRead(); A() = asr(A()); break; // ASR (ASRA inherent) + case 0x57: memoryRead(); B() = asr(B()); break; // ASR (ASRB inherent) + case 0x67: RMW(AM_indexed_byte, asr); break; // ASR (indexed) + case 0x77: RMW(AM_extended_byte, asr); break; // ASR (extended) // BIT - case 0x85: tick(2); bit(A(), AM_immediate_byte()); break; // BIT (BITA immediate) - case 0x95: tick(4); bit(A(), AM_direct_byte()); break; // BIT (BITA direct) - case 0xa5: tick(4); bit(A(), AM_indexed_byte()); break; // BIT (BITA indexed) - case 0xb5: tick(5); bit(A(), AM_extended_byte()); break; // BIT (BITA extended) + case 0x85: bit(A(), AM_immediate_byte()); break; // BIT (BITA immediate) + case 0x95: bit(A(), AM_direct_byte()); break; // BIT (BITA direct) + case 0xa5: bit(A(), AM_indexed_byte()); break; // BIT (BITA indexed) + case 0xb5: bit(A(), AM_extended_byte()); break; // BIT (BITA extended) - case 0xc5: tick(2); bit(B(), AM_immediate_byte()); break; // BIT (BITB immediate) - case 0xd5: tick(4); bit(B(), AM_direct_byte()); break; // BIT (BITB direct) - case 0xe5: tick(4); bit(B(), AM_indexed_byte()); break; // BIT (BITB indexed) - case 0xf5: tick(5); bit(B(), AM_extended_byte()); break; // BIT (BITB extended) + case 0xc5: bit(B(), AM_immediate_byte()); break; // BIT (BITB immediate) + case 0xd5: bit(B(), AM_direct_byte()); break; // BIT (BITB direct) + case 0xe5: bit(B(), AM_indexed_byte()); break; // BIT (BITB indexed) + case 0xf5: bit(B(), AM_extended_byte()); break; // BIT (BITB extended) // CLR - case 0x0f: tick(6); memoryWrite(Address_direct(), clr()); break; // CLR (direct) - case 0x4f: tick(2); A() = clr(); break; // CLR (CLRA implied) - case 0x5f: tick(2); B() = clr(); break; // CLR (CLRB implied) - case 0x6f: tick(6); memoryWrite(Address_indexed(), clr()); break; // CLR (indexed) - case 0x7f: tick(7); memoryWrite(Address_extended(), clr()); break; // CLR (extended) + case 0x0f: RMW(AM_direct_byte, clr); break; // CLR (direct) + case 0x4f: memoryRead(); A() = clr(); break; // CLR (CLRA implied) + case 0x5f: memoryRead(); B() = clr(); break; // CLR (CLRB implied) + case 0x6f: RMW(AM_indexed_byte, clr); break; // CLR (indexed) + case 0x7f: RMW(AM_extended_byte, clr); break; // CLR (extended) // CMP // CMPA - case 0x81: tick(2); cmp(A(), AM_immediate_byte()); break; // CMP (CMPA, immediate) - case 0x91: tick(4); cmp(A(), AM_direct_byte()); break; // CMP (CMPA, direct) - case 0xa1: tick(4); cmp(A(), AM_indexed_byte()); break; // CMP (CMPA, indexed) - case 0xb1: tick(5); cmp(A(), AM_extended_byte()); break; // CMP (CMPA, extended) + case 0x81: cmp(A(), AM_immediate_byte()); break; // CMP (CMPA, immediate) + case 0x91: cmp(A(), AM_direct_byte()); break; // CMP (CMPA, direct) + case 0xa1: cmp(A(), AM_indexed_byte()); break; // CMP (CMPA, indexed) + case 0xb1: cmp(A(), AM_extended_byte()); break; // CMP (CMPA, extended) // CMPB - case 0xc1: tick(2); cmp(B(), AM_immediate_byte()); break; // CMP (CMPB, immediate) - case 0xd1: tick(4); cmp(B(), AM_direct_byte()); break; // CMP (CMPB, direct) - case 0xe1: tick(4); cmp(B(), AM_indexed_byte()); break; // CMP (CMPB, indexed) - case 0xf1: tick(5); cmp(B(), AM_extended_byte()); break; // CMP (CMPB, extended) + case 0xc1: cmp(B(), AM_immediate_byte()); break; // CMP (CMPB, immediate) + case 0xd1: cmp(B(), AM_direct_byte()); break; // CMP (CMPB, direct) + case 0xe1: cmp(B(), AM_indexed_byte()); break; // CMP (CMPB, indexed) + case 0xf1: cmp(B(), AM_extended_byte()); break; // CMP (CMPB, extended) // CMPX - case 0x8c: tick(4); cmp(X(), AM_immediate_word()); break; // CMP (CMPX, immediate) - case 0x9c: tick(6); cmp(X(), AM_direct_word()); break; // CMP (CMPX, direct) - case 0xac: tick(6); cmp(X(), AM_indexed_word()); break; // CMP (CMPX, indexed) - case 0xbc: tick(7); cmp(X(), AM_extended_word()); break; // CMP (CMPX, extended) + case 0x8c: cmp(X(), AM_immediate_word()); break; // CMP (CMPX, immediate) + case 0x9c: cmp(X(), AM_direct_word()); break; // CMP (CMPX, direct) + case 0xac: cmp(X(), AM_indexed_word()); break; // CMP (CMPX, indexed) + case 0xbc: cmp(X(), AM_extended_word()); break; // CMP (CMPX, extended) // COM - case 0x03: tick(6); memoryWrite(com(AM_direct_byte())); break; // COM (direct) - case 0x43: tick(2); A() = com(A()); break; // COM (COMA inherent) - case 0x53: tick(2); B() = com(B()); break; // COM (COMB inherent) - case 0x63: tick(6); memoryWrite(com(AM_indexed_byte())); break; // COM (indexed) - case 0x73: tick(7); memoryWrite(com(AM_extended_byte())); break; // COM (extended) + case 0x03: RMW(AM_direct_byte, com); break; // COM (direct) + case 0x43: memoryRead(); A() = com(A()); break; // COM (COMA inherent) + case 0x53: memoryRead(); B() = com(B()); break; // COM (COMB inherent) + case 0x63: RMW(AM_indexed_byte, com); break; // COM (indexed) + case 0x73: RMW(AM_extended_byte, com); break; // COM (extended) // CWAI - case 0x3c: tick(11); cwai(AM_direct_byte()); break; // CWAI (direct) + case 0x3c: cwai(AM_direct_byte()); break; // CWAI (direct) // DAA - case 0x19: tick(2); A() = da(A()); break; // DAA (inherent) + case 0x19: memoryRead(); A() = da(A()); break; // DAA (inherent) // DEC - case 0x0a: tick(6); memoryWrite(dec(AM_direct_byte())); break; // DEC (direct) - case 0x4a: tick(2); A() = dec(A()); break; // DEC (DECA inherent) - case 0x5a: tick(2); B() = dec(B()); break; // DEC (DECB inherent) - case 0x6a: tick(6); memoryWrite(dec(AM_indexed_byte())); break; // DEC (indexed) - case 0x7a: tick(7); memoryWrite(dec(AM_extended_byte())); break; // DEC (extended) + case 0x0a: RMW(AM_direct_byte, dec); break; // DEC (direct) + case 0x4a: memoryRead(); A() = dec(A()); break; // DEC (DECA inherent) + case 0x5a: memoryRead(); B() = dec(B()); break; // DEC (DECB inherent) + case 0x6a: RMW(AM_indexed_byte, dec); break; // DEC (indexed) + case 0x7a: RMW(AM_extended_byte, dec); break; // DEC (extended) // EOR // EORA - case 0x88: tick(2); A() = eorr(A(), AM_immediate_byte()); break; // EOR (EORA immediate) - case 0x98: tick(4); A() = eorr(A(), AM_direct_byte()); break; // EOR (EORA direct) - case 0xa8: tick(4); A() = eorr(A(), AM_indexed_byte()); break; // EOR (EORA indexed) - case 0xb8: tick(5); A() = eorr(A(), AM_extended_byte()); break; // EOR (EORA extended) + case 0x88: A() = eorr(A(), AM_immediate_byte()); break; // EOR (EORA immediate) + case 0x98: A() = eorr(A(), AM_direct_byte()); break; // EOR (EORA direct) + case 0xa8: A() = eorr(A(), AM_indexed_byte()); break; // EOR (EORA indexed) + case 0xb8: A() = eorr(A(), AM_extended_byte()); break; // EOR (EORA extended) // EORB - case 0xc8: tick(2); B() = eorr(B(), AM_immediate_byte()); break; // EOR (EORB immediate) - case 0xd8: tick(4); B() = eorr(B(), AM_direct_byte()); break; // EOR (EORB direct) - case 0xe8: tick(4); B() = eorr(B(), AM_indexed_byte()); break; // EOR (EORB indexed) - case 0xf8: tick(5); B() = eorr(B(), AM_extended_byte()); break; // EOR (EORB extended) + case 0xc8: B() = eorr(B(), AM_immediate_byte()); break; // EOR (EORB immediate) + case 0xd8: B() = eorr(B(), AM_direct_byte()); break; // EOR (EORB direct) + case 0xe8: B() = eorr(B(), AM_indexed_byte()); break; // EOR (EORB indexed) + case 0xf8: B() = eorr(B(), AM_extended_byte()); break; // EOR (EORB extended) // EXG - case 0x1e: tick(8); exg(AM_immediate_byte()); break; // EXG (R1,R2 immediate) + case 0x1e: exg(AM_immediate_byte()); break; // EXG (R1,R2 immediate) // INC - case 0x0c: tick(6); memoryWrite(inc(AM_direct_byte())); break; // INC (direct) - case 0x4c: tick(2); A() = inc(A()); break; // INC (INCA inherent) - case 0x5c: tick(2); B() = inc(B()); break; // INC (INCB inherent) - case 0x6c: tick(6); memoryWrite(inc(AM_indexed_byte())); break; // INC (indexed) - case 0x7c: tick(7); memoryWrite(inc(AM_extended_byte())); break; // INC (extended) + case 0x0c: RMW(AM_direct_byte, inc); break; // INC (direct) + case 0x4c: memoryRead(); A() = inc(A()); break; // INC (INCA inherent) + case 0x5c: memoryRead(); B() = inc(B()); break; // INC (INCB inherent) + case 0x6c: RMW(AM_indexed_byte, inc); break; // INC (indexed) + case 0x7c: RMW(AM_extended_byte, inc); break; // INC (extended) // JMP - case 0x0e: tick(6); jump(Address_direct()); break; // JMP (direct) - case 0x6e: tick(6); jump(Address_indexed()); break; // JMP (indexed) - case 0x7e: tick(7); jump(Address_extended()); break; // JMP (extended) + case 0x0e: jump(Address_direct()); break; // JMP (direct) + case 0x6e: jump(Address_indexed()); break; // JMP (indexed) + case 0x7e: jump(Address_extended()); break; // JMP (extended) // JSR - case 0x9d: tick(6); jsr(Address_direct()); break; // JSR (direct) - case 0xad: tick(6); jsr(Address_indexed()); break; // JSR (indexed) - case 0xbd: tick(7); jsr(Address_extended()); break; // JSR (extended) + case 0x9d: jsr(Address_direct()); break; // JSR (direct) + case 0xad: jsr(Address_indexed()); break; // JSR (indexed) + case 0xbd: jsr(Address_extended()); break; // JSR (extended) // LD // LDA - case 0x86: tick(2); A() = ld(AM_immediate_byte()); break; // LD (LDA immediate) - case 0x96: tick(4); A() = ld(AM_direct_byte()); break; // LD (LDA direct) - case 0xa6: tick(4); A() = ld(AM_indexed_byte()); break; // LD (LDA indexed) - case 0xb6: tick(5); A() = ld(AM_extended_byte()); break; // LD (LDA extended) + 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) // LDB - case 0xc6: tick(2); B() = ld(AM_immediate_byte()); break; // LD (LDB immediate) - case 0xd6: tick(4); B() = ld(AM_direct_byte()); break; // LD (LDB direct) - case 0xe6: tick(4); B() = ld(AM_indexed_byte()); break; // LD (LDB indexed) - case 0xf6: tick(5); B() = ld(AM_extended_byte()); break; // LD (LDB extended) + 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) // LDD - case 0xcc: tick(3); D() = ld(AM_immediate_word()); break; // LD (LDD immediate) - case 0xdc: tick(5); D() = ld(AM_direct_word()); break; // LD (LDD direct) - case 0xec: tick(5); D() = ld(AM_indexed_word()); break; // LD (LDD indexed) - case 0xfc: tick(6); D() = ld(AM_extended_word()); break; // LD (LDD extended) + 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) // LDU - case 0xce: tick(3); U() = ld(AM_immediate_word()); break; // LD (LDU immediate) - case 0xde: tick(5); U() = ld(AM_direct_word()); break; // LD (LDU direct) - case 0xee: tick(5); U() = ld(AM_indexed_word()); break; // LD (LDU indexed) - case 0xfe: tick(6); U() = ld(AM_extended_word()); break; // LD (LDU extended) + 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) // LDX - case 0x8e: tick(3); X() = ld(AM_immediate_word()); break; // LD (LDX immediate) - case 0x9e: tick(5); X() = ld(AM_direct_word()); break; // LD (LDX direct) - case 0xae: tick(5); X() = ld(AM_indexed_word()); break; // LD (LDX indexed) - case 0xbe: tick(6); X() = ld(AM_extended_word()); break; // LD (LDX extended) + 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) // LEA - case 0x30: tick(4); adjustZero(X() = Address_indexed()); break; // LEA (LEAX indexed) - case 0x31: tick(4); adjustZero(Y() = Address_indexed()); break; // LEA (LEAY indexed) - case 0x32: tick(4); S() = Address_indexed(); break; // LEA (LEAS indexed) - case 0x33: tick(4); U() = Address_indexed(); break; // LEA (LEAU indexed) + case 0x30: adjustZero(X() = Address_indexed()); break; // LEA (LEAX indexed) + case 0x31: adjustZero(Y() = Address_indexed()); break; // LEA (LEAY indexed) + case 0x32: S() = Address_indexed(); break; // LEA (LEAS indexed) + case 0x33: U() = Address_indexed(); break; // LEA (LEAU indexed) // LSR - case 0x04: tick(6); memoryWrite(lsr(AM_direct_byte())); break; // LSR (direct) - case 0x44: tick(2); A() = lsr(A()); break; // LSR (LSRA inherent) - case 0x54: tick(2); B() = lsr(B()); break; // LSR (LSRB inherent) - case 0x64: tick(6); memoryWrite(lsr(AM_indexed_byte())); break; // LSR (indexed) - case 0x74: tick(7); memoryWrite(lsr(AM_extended_byte())); break; // LSR (extended) + case 0x04: RMW(AM_direct_byte, lsr); break; // LSR (direct) + case 0x44: memoryRead(); A() = lsr(A()); break; // LSR (LSRA inherent) + case 0x54: memoryRead(); B() = lsr(B()); break; // LSR (LSRB inherent) + case 0x64: RMW(AM_indexed_byte, lsr); break; // LSR (indexed) + case 0x74: RMW(AM_extended_byte, lsr); break; // LSR (extended) // MUL - case 0x3d: tick(11); D() = mul(A(), B()); break; // MUL (inherent) + case 0x3d: memoryRead(); D() = mul(A(), B()); break; // MUL (inherent) // NEG - case 0x00: tick(6); memoryWrite(neg(AM_direct_byte())); break; // NEG (direct) - case 0x40: tick(2); A() = neg(A()); break; // NEG (NEGA, inherent) - case 0x50: tick(2); B() = neg(B()); break; // NEG (NEGB, inherent) - case 0x60: tick(6); memoryWrite(neg(AM_indexed_byte())); break; // NEG (indexed) - case 0x70: tick(7); memoryWrite(neg(AM_extended_byte())); break; // NEG (extended) + case 0x00: RMW(AM_direct_byte, neg); break; // NEG (direct) + case 0x40: memoryRead(); A() = neg(A()); break; // NEG (NEGA, inherent) + case 0x50: memoryRead(); B() = neg(B()); break; // NEG (NEGB, inherent) + case 0x60: RMW(AM_indexed_byte, neg); break; // NEG (indexed) + case 0x70: RMW(AM_extended_byte, neg); break; // NEG (extended) // NOP - case 0x12: tick(2); break; // NOP (inherent) + case 0x12: memoryRead(); break; // NOP (inherent) // OR // ORA - case 0x8a: tick(2); A() = orr(A(), AM_immediate_byte()); break; // OR (ORA immediate) - case 0x9a: tick(4); A() = orr(A(), AM_direct_byte()); break; // OR (ORA direct) - case 0xaa: tick(4); A() = orr(A(), AM_indexed_byte()); break; // OR (ORA indexed) - case 0xba: tick(5); A() = orr(A(), AM_extended_byte()); break; // OR (ORA extended) + case 0x8a: A() = orr(A(), AM_immediate_byte()); break; // OR (ORA immediate) + case 0x9a: A() = orr(A(), AM_direct_byte()); break; // OR (ORA direct) + case 0xaa: A() = orr(A(), AM_indexed_byte()); break; // OR (ORA indexed) + case 0xba: A() = orr(A(), AM_extended_byte()); break; // OR (ORA extended) // ORB - case 0xca: tick(2); B() = orr(B(), AM_immediate_byte()); break; // OR (ORB immediate) - case 0xda: tick(4); B() = orr(B(), AM_direct_byte()); break; // OR (ORB direct) - case 0xea: tick(4); B() = orr(B(), AM_indexed_byte()); break; // OR (ORB indexed) - case 0xfa: tick(5); B() = orr(B(), AM_extended_byte()); break; // OR (ORB extended) + case 0xca: B() = orr(B(), AM_immediate_byte()); break; // OR (ORB immediate) + case 0xda: B() = orr(B(), AM_direct_byte()); break; // OR (ORB direct) + case 0xea: B() = orr(B(), AM_indexed_byte()); break; // OR (ORB indexed) + case 0xfa: B() = orr(B(), AM_extended_byte()); break; // OR (ORB extended) // ORCC - case 0x1a: tick(3); CC() |= AM_immediate_byte(); break; // OR (ORCC immediate) + case 0x1a: CC() |= AM_immediate_byte(); break; // OR (ORCC immediate) // PSH - case 0x34: tick(5); psh(S(), AM_immediate_byte()); break; // PSH (PSHS immediate) - case 0x36: tick(5); psh(U(), AM_immediate_byte()); break; // PSH (PSHU immediate) + case 0x34: psh(S(), AM_immediate_byte()); break; // PSH (PSHS immediate) + case 0x36: psh(U(), AM_immediate_byte()); break; // PSH (PSHU immediate) // PUL - case 0x35: tick(5); pul(S(), AM_immediate_byte()); break; // PUL (PULS immediate) - case 0x37: tick(5); pul(U(), AM_immediate_byte()); break; // PUL (PULU immediate) + case 0x35: pul(S(), AM_immediate_byte()); break; // PUL (PULS immediate) + case 0x37: pul(U(), AM_immediate_byte()); break; // PUL (PULU immediate) // ROL - case 0x09: tick(6); memoryWrite(rol(AM_direct_byte())); break; // ROL (direct) - case 0x49: tick(2); A() = rol(A()); break; // ROL (ROLA inherent) - case 0x59: tick(2); B() = rol(B()); break; // ROL (ROLB inherent) - case 0x69: tick(6); memoryWrite(rol(AM_indexed_byte())); break; // ROL (indexed) - case 0x79: tick(7); memoryWrite(rol(AM_extended_byte())); break; // ROL (extended) + case 0x09: RMW(AM_direct_byte, rol); break; // ROL (direct) + case 0x49: memoryRead(); A() = rol(A()); break; // ROL (ROLA inherent) + case 0x59: memoryRead(); B() = rol(B()); break; // ROL (ROLB inherent) + case 0x69: RMW(AM_indexed_byte, rol); break; // ROL (indexed) + case 0x79: RMW(AM_extended_byte, rol); break; // ROL (extended) // ROR - case 0x06: tick(6); memoryWrite(ror(AM_direct_byte())); break; // ROR (direct) - case 0x46: tick(2); A() = ror(A()); break; // ROR (RORA inherent) - case 0x56: tick(2); B() = ror(B()); break; // ROR (RORB inherent) - case 0x66: tick(6); memoryWrite(ror(AM_indexed_byte())); break; // ROR (indexed) - case 0x76: tick(7); memoryWrite(ror(AM_extended_byte())); break; // ROR (extended) + case 0x06: RMW(AM_direct_byte, ror); break; // ROR (direct) + case 0x46: memoryRead(); A() = ror(A()); break; // ROR (RORA inherent) + case 0x56: memoryRead(); B() = ror(B()); break; // ROR (RORB inherent) + case 0x66: RMW(AM_indexed_byte, ror); break; // ROR (indexed) + case 0x76: RMW(AM_extended_byte, ror); break; // ROR (extended) // RTI - case 0x3B: tick(6); rti(); break; // RTI (inherent) + case 0x3B: memoryRead(); rti(); break; // RTI (inherent) // RTS - case 0x39: tick(5); rts(); break; // RTS (inherent) + case 0x39: memoryRead(); rts(); break; // RTS (inherent) // SBC // SBCA - case 0x82: tick(4); A() = sbc(A(), AM_immediate_byte()); break; // SBC (SBCA immediate) - case 0x92: tick(4); A() = sbc(A(), AM_direct_byte()); break; // SBC (SBCA direct) - case 0xa2: tick(4); A() = sbc(A(), AM_indexed_byte()); break; // SBC (SBCA indexed) - case 0xb2: tick(5); A() = sbc(A(), AM_extended_byte()); break; // SBC (SBCB extended) + case 0x82: A() = sbc(A(), AM_immediate_byte()); break; // SBC (SBCA immediate) + case 0x92: A() = sbc(A(), AM_direct_byte()); break; // SBC (SBCA direct) + case 0xa2: A() = sbc(A(), AM_indexed_byte()); break; // SBC (SBCA indexed) + case 0xb2: A() = sbc(A(), AM_extended_byte()); break; // SBC (SBCB extended) // SBCB - case 0xc2: tick(4); B() = sbc(B(), AM_immediate_byte()); break; // SBC (SBCB immediate) - case 0xd2: tick(4); B() = sbc(B(), AM_direct_byte()); break; // SBC (SBCB direct) - case 0xe2: tick(4); B() = sbc(B(), AM_indexed_byte()); break; // SBC (SBCB indexed) - case 0xf2: tick(5); B() = sbc(B(), AM_extended_byte()); break; // SBC (SBCB extended) + case 0xc2: B() = sbc(B(), AM_immediate_byte()); break; // SBC (SBCB immediate) + case 0xd2: B() = sbc(B(), AM_direct_byte()); break; // SBC (SBCB direct) + case 0xe2: B() = sbc(B(), AM_indexed_byte()); break; // SBC (SBCB indexed) + case 0xf2: B() = sbc(B(), AM_extended_byte()); break; // SBC (SBCB extended) // SEX - case 0x1d: tick(2); A() = sex(B()); break; // SEX (inherent) + case 0x1d: memoryRead(); A() = sex(B()); break; // SEX (inherent) // ST // STA - case 0x97: tick(4); memoryWrite(Address_direct(), st(A())); break; // ST (STA direct) - case 0xa7: tick(4); memoryWrite(Address_indexed(), st(A())); break; // ST (STA indexed) - case 0xb7: tick(5); memoryWrite(Address_extended(), st(A())); break; // ST (STA extended) + 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) // STB - case 0xd7: tick(4); memoryWrite(Address_direct(), st(B())); break; // ST (STB direct) - case 0xe7: tick(4); memoryWrite(Address_indexed(), st(B())); break; // ST (STB indexed) - case 0xf7: tick(5); memoryWrite(Address_extended(), st(B())); break; // ST (STB extended) + 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) // STD - case 0xdd: tick(5); Processor::setWord(Address_direct(), st(D())); break; // ST (STD direct) - case 0xed: tick(5); Processor::setWord(Address_indexed(), st(D())); break; // ST (STD indexed) - case 0xfd: tick(6); Processor::setWord(Address_extended(), st(D())); break; // ST (STD extended) + 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) // STU - case 0xdf: tick(5); Processor::setWord(Address_direct(), st(U())); break; // ST (STU direct) - case 0xef: tick(5); Processor::setWord(Address_indexed(), st(U())); break; // ST (STU indexed) - case 0xff: tick(6); Processor::setWord(Address_extended(), st(U())); break; // ST (STU extended) + 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) // STX - case 0x9f: tick(5); Processor::setWord(Address_direct(), st(X())); break; // ST (STX direct) - case 0xaf: tick(5); Processor::setWord(Address_indexed(), st(X())); break; // ST (STX indexed) - case 0xbf: tick(6); Processor::setWord(Address_extended(), st(X())); break; // ST (STX extended) + 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) // SUB // SUBA - case 0x80: tick(2); A() = sub(A(), AM_immediate_byte()); break; // SUB (SUBA immediate) - case 0x90: tick(4); A() = sub(A(), AM_direct_byte()); break; // SUB (SUBA direct) - case 0xa0: tick(4); A() = sub(A(), AM_indexed_byte()); break; // SUB (SUBA indexed) - case 0xb0: tick(5); A() = sub(A(), AM_extended_byte()); break; // SUB (SUBA extended) + case 0x80: A() = sub(A(), AM_immediate_byte()); break; // SUB (SUBA immediate) + case 0x90: A() = sub(A(), AM_direct_byte()); break; // SUB (SUBA direct) + case 0xa0: A() = sub(A(), AM_indexed_byte()); break; // SUB (SUBA indexed) + case 0xb0: A() = sub(A(), AM_extended_byte()); break; // SUB (SUBA extended) // SUBB - case 0xc0: tick(2); B() = sub(B(), AM_immediate_byte()); break; // SUB (SUBB immediate) - case 0xd0: tick(4); B() = sub(B(), AM_direct_byte()); break; // SUB (SUBB direct) - case 0xe0: tick(4); B() = sub(B(), AM_indexed_byte()); break; // SUB (SUBB indexed) - case 0xf0: tick(5); B() = sub(B(), AM_extended_byte()); break; // SUB (SUBB extended) + case 0xc0: B() = sub(B(), AM_immediate_byte()); break; // SUB (SUBB immediate) + case 0xd0: B() = sub(B(), AM_direct_byte()); break; // SUB (SUBB direct) + case 0xe0: B() = sub(B(), AM_indexed_byte()); break; // SUB (SUBB indexed) + case 0xf0: B() = sub(B(), AM_extended_byte()); break; // SUB (SUBB extended) // SUBD - case 0x83: tick(4); D() = sub(D(), AM_immediate_word()); break; // SUB (SUBD immediate) - case 0x93: tick(6); D() = sub(D(), AM_direct_word()); break; // SUB (SUBD direct) - case 0xa3: tick(6); D() = sub(D(), AM_indexed_word()); break; // SUB (SUBD indexed) - case 0xb3: tick(7); D() = sub(D(), AM_extended_word()); break; // SUB (SUBD extended) + case 0x83: D() = sub(D(), AM_immediate_word()); break; // SUB (SUBD immediate) + case 0x93: D() = sub(D(), AM_direct_word()); break; // SUB (SUBD direct) + case 0xa3: D() = sub(D(), AM_indexed_word()); break; // SUB (SUBD indexed) + case 0xb3: D() = sub(D(), AM_extended_word()); break; // SUB (SUBD extended) // SWI - case 0x3f: tick(10); swi(); break; // SWI (inherent) + case 0x3f: memoryRead(); swi(); break; // SWI (inherent) XXXX // SYNC - case 0x13: tick(4); halt(); break; // SYNC (inherent) + case 0x13: memoryRead(); halt(); break; // SYNC (inherent)XXXX // TFR - case 0x1f: tick(6); tfr(AM_immediate_byte()); break; // TFR (immediate) + case 0x1f: tfr(AM_immediate_byte()); break; // TFR (immediate) // TST - case 0x0d: tick(6); tst(AM_direct_byte()); break; // TST (direct) - case 0x4d: tick(2); tst(A()); break; // TST (TSTA inherent) - case 0x5d: tick(2); tst(B()); break; // TST (TSTB inherent) - case 0x6d: tick(6); tst(AM_indexed_byte()); break; // TST (indexed) - case 0x7d: tick(7); tst(AM_extended_byte()); break; // TST (extended) + case 0x0d: tst(AM_direct_byte()); break; // TST (direct) + case 0x4d: memoryRead(); tst(A()); break; // TST (TSTA inherent) + case 0x5d: memoryRead(); tst(B()); break; // TST (TSTB inherent) + case 0x6d: tst(AM_indexed_byte()); break; // TST (indexed) + case 0x7d: tst(AM_extended_byte()); break; // TST (extended) // Branching - case 0x16: tick(5); jump(Address_relative_word()); break; // BRA (LBRA relative) - case 0x17: tick(9); jsr(Address_relative_word()); break; // BSR (LBSR relative) - case 0x20: tick(3); jump(Address_relative_byte()); break; // BRA (relative) - case 0x21: tick(3); Address_relative_byte(); break; // BRN (relative) - case 0x22: tick(3); branchShort(HI()); break; // BHI (relative) - case 0x23: tick(3); branchShort(LS()); break; // BLS (relative) - case 0x24: tick(3); branchShort(!carry()); break; // BCC (relative) - case 0x25: tick(3); branchShort(carry()); break; // BCS (relative) - case 0x26: tick(3); branchShort(!zero()); break; // BNE (relative) - case 0x27: tick(3); branchShort(zero()); break; // BEQ (relative) - case 0x28: tick(3); branchShort(!overflow()); break; // BVC (relative) - case 0x29: tick(3); branchShort(overflow()); break; // BVS (relative) - case 0x2a: tick(3); branchShort(!negative()); break; // BPL (relative) - case 0x2b: tick(3); branchShort(negative()); break; // BMI (relative) - case 0x2c: tick(3); branchShort(GE()); break; // BGE (relative) - case 0x2d: tick(3); branchShort(LT()); break; // BLT (relative) - case 0x2e: tick(3); branchShort(GT()); break; // BGT (relative) - case 0x2f: tick(3); branchShort(LE()); break; // BLE (relative) + case 0x16: jump(Address_relative_word()); break; // BRA (LBRA relative) + case 0x17: jsr(Address_relative_word()); break; // BSR (LBSR relative) + case 0x20: jump(Address_relative_byte()); break; // BRA (relative) + case 0x21: Address_relative_byte(); break; // BRN (relative) + case 0x22: branchShort(HI()); break; // BHI (relative) + case 0x23: branchShort(LS()); break; // BLS (relative) + case 0x24: branchShort(!carry()); break; // BCC (relative) + case 0x25: branchShort(carry()); break; // BCS (relative) + case 0x26: branchShort(!zero()); break; // BNE (relative) + case 0x27: branchShort(zero()); break; // BEQ (relative) + case 0x28: branchShort(!overflow()); break; // BVC (relative) + case 0x29: branchShort(overflow()); break; // BVS (relative) + case 0x2a: branchShort(!negative()); break; // BPL (relative) + case 0x2b: branchShort(negative()); break; // BMI (relative) + case 0x2c: branchShort(GE()); break; // BGE (relative) + case 0x2d: branchShort(LT()); break; // BLT (relative) + case 0x2e: branchShort(GT()); break; // BGT (relative) + case 0x2f: branchShort(LE()); break; // BLE (relative) - case 0x8d: tick(7); jsr(Address_relative_byte()); break; // BSR (relative) + case 0x8d: jsr(Address_relative_byte()); break; // BSR (relative) default: UNREACHABLE; @@ -497,68 +534,68 @@ void EightBit::mc6809::executeUnprefixed() { void EightBit::mc6809::execute10() { assert(m_prefix10 && !m_prefix11); - assert(cycles() == 0); + assert(cycles() == 2); // Two fetches switch (opcode()) { // CMP // CMPD - case 0x83: tick(5); cmp(D(), AM_immediate_word()); break; // CMP (CMPD, immediate) - case 0x93: tick(7); cmp(D(), AM_direct_word()); break; // CMP (CMPD, direct) - case 0xa3: tick(7); cmp(D(), AM_indexed_word()); break; // CMP (CMPD, indexed) - case 0xb3: tick(8); cmp(D(), AM_extended_word()); break; // CMP (CMPD, extended) + case 0x83: cmp(D(), AM_immediate_word()); break; // CMP (CMPD, immediate) + case 0x93: cmp(D(), AM_direct_word()); break; // CMP (CMPD, direct) + case 0xa3: cmp(D(), AM_indexed_word()); break; // CMP (CMPD, indexed) + case 0xb3: cmp(D(), AM_extended_word()); break; // CMP (CMPD, extended) // CMPY - case 0x8c: tick(5); cmp(Y(), AM_immediate_word()); break; // CMP (CMPY, immediate) - case 0x9c: tick(7); cmp(Y(), AM_direct_word()); break; // CMP (CMPY, direct) - case 0xac: tick(7); cmp(Y(), AM_indexed_word()); break; // CMP (CMPY, indexed) - case 0xbc: tick(8); cmp(Y(), AM_extended_word()); break; // CMP (CMPY, extended) + case 0x8c: cmp(Y(), AM_immediate_word()); break; // CMP (CMPY, immediate) + case 0x9c: cmp(Y(), AM_direct_word()); break; // CMP (CMPY, direct) + case 0xac: cmp(Y(), AM_indexed_word()); break; // CMP (CMPY, indexed) + case 0xbc: cmp(Y(), AM_extended_word()); break; // CMP (CMPY, extended) // LD // LDS - case 0xce: tick(4); S() = ld(AM_immediate_word()); break; // LD (LDS immediate) - case 0xde: tick(6); S() = ld(AM_direct_word()); break; // LD (LDS direct) - case 0xee: tick(6); S() = ld(AM_indexed_word()); break; // LD (LDS indexed) - case 0xfe: tick(7); S() = ld(AM_extended_word()); break; // LD (LDS extended) + 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) // LDY - case 0x8e: tick(4); Y() = ld(AM_immediate_word()); break; // LD (LDY immediate) - case 0x9e: tick(6); Y() = ld(AM_direct_word()); break; // LD (LDY direct) - case 0xae: tick(6); Y() = ld(AM_indexed_word()); break; // LD (LDY indexed) - case 0xbe: tick(7); Y() = ld(AM_extended_word()); break; // LD (LDY extended) + 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) // Branching - case 0x21: tick(5); Address_relative_word(); break; // BRN (LBRN relative) - case 0x22: tick(5); branchLong(HI()); break; // BHI (LBHI relative) - case 0x23: tick(5); branchLong(LS()); break; // BLS (LBLS relative) - case 0x24: tick(5); branchLong(!carry()); break; // BCC (LBCC relative) - case 0x25: tick(5); branchLong(carry()); break; // BCS (LBCS relative) - case 0x26: tick(5); branchLong(!zero()); break; // BNE (LBNE relative) - case 0x27: tick(5); branchLong(zero()); break; // BEQ (LBEQ relative) - case 0x28: tick(5); branchLong(!overflow()); break; // BVC (LBVC relative) - case 0x29: tick(5); branchLong(overflow()); break; // BVS (LBVS relative) - case 0x2a: tick(5); branchLong(!negative()); break; // BPL (LBPL relative) - case 0x2b: tick(5); branchLong(negative()); break; // BMI (LBMI relative) - case 0x2c: tick(5); branchLong(GE()); break; // BGE (LBGE relative) - case 0x2d: tick(5); branchLong(LT()); break; // BLT (LBLT relative) - case 0x2e: tick(5); branchLong(GT()); break; // BGT (LBGT relative) - case 0x2f: tick(5); branchLong(LE()); break; // BLE (LBLE relative) + case 0x21: Address_relative_word(); break; // BRN (LBRN relative) + case 0x22: branchLong(HI()); break; // BHI (LBHI relative) + case 0x23: branchLong(LS()); break; // BLS (LBLS relative) + case 0x24: branchLong(!carry()); break; // BCC (LBCC relative) + case 0x25: branchLong(carry()); break; // BCS (LBCS relative) + case 0x26: branchLong(!zero()); break; // BNE (LBNE relative) + case 0x27: branchLong(zero()); break; // BEQ (LBEQ relative) + case 0x28: branchLong(!overflow()); break; // BVC (LBVC relative) + case 0x29: branchLong(overflow()); break; // BVS (LBVS relative) + case 0x2a: branchLong(!negative()); break; // BPL (LBPL relative) + case 0x2b: branchLong(negative()); break; // BMI (LBMI relative) + case 0x2c: branchLong(GE()); break; // BGE (LBGE relative) + case 0x2d: branchLong(LT()); break; // BLT (LBLT relative) + case 0x2e: branchLong(GT()); break; // BGT (LBGT relative) + case 0x2f: branchLong(LE()); break; // BLE (LBLE relative) // STS - case 0xdf: tick(6); Processor::setWord(Address_direct(), st(S())); break; // ST (STS direct) - case 0xef: tick(6); Processor::setWord(Address_indexed(), st(S())); break; // ST (STS indexed) - case 0xff: tick(7); Processor::setWord(Address_extended(), st(S())); break; // ST (STS extended) + 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) // STY - case 0x9f: tick(6); Processor::setWord(Address_direct(), st(Y())); break; // ST (STY direct) - case 0xaf: tick(6); Processor::setWord(Address_indexed(), st(Y())); break; // ST (STY indexed) - case 0xbf: tick(7); Processor::setWord(Address_extended(), st(Y())); break; // ST (STY extended) + 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) // SWI - case 0x3f: tick(11); swi2(); break; // SWI (SWI2 inherent) + case 0x3f: memoryRead(); swi2(); break; // SWI (SWI2 inherent) default: UNREACHABLE; @@ -568,26 +605,26 @@ void EightBit::mc6809::execute10() { void EightBit::mc6809::execute11() { assert(!m_prefix10 && m_prefix11); - assert(cycles() == 0); + assert(cycles() == 2); // Two fetches switch (opcode()) { // CMP // CMPU - case 0x83: tick(5); cmp(U(), AM_immediate_word()); break; // CMP (CMPU, immediate) - case 0x93: tick(7); cmp(U(), AM_direct_word()); break; // CMP (CMPU, direct) - case 0xa3: tick(7); cmp(U(), AM_indexed_word()); break; // CMP (CMPU, indexed) - case 0xb3: tick(8); cmp(U(), AM_extended_word()); break; // CMP (CMPU, extended) + case 0x83: cmp(U(), AM_immediate_word()); break; // CMP (CMPU, immediate) + case 0x93: cmp(U(), AM_direct_word()); break; // CMP (CMPU, direct) + case 0xa3: cmp(U(), AM_indexed_word()); break; // CMP (CMPU, indexed) + case 0xb3: cmp(U(), AM_extended_word()); break; // CMP (CMPU, extended) // CMPS - case 0x8c: tick(5); cmp(S(), AM_immediate_word()); break; // CMP (CMPS, immediate) - case 0x9c: tick(7); cmp(S(), AM_direct_word()); break; // CMP (CMPS, direct) - case 0xac: tick(7); cmp(S(), AM_indexed_word()); break; // CMP (CMPS, indexed) - case 0xbc: tick(8); cmp(S(), AM_extended_word()); break; // CMP (CMPS, extended) + case 0x8c: cmp(S(), AM_immediate_word()); break; // CMP (CMPS, immediate) + case 0x9c: cmp(S(), AM_direct_word()); break; // CMP (CMPS, direct) + case 0xac: cmp(S(), AM_indexed_word()); break; // CMP (CMPS, indexed) + case 0xbc: cmp(S(), AM_extended_word()); break; // CMP (CMPS, extended) // SWI - case 0x3f: tick(11); swi3(); break; // SWI (SWI3 inherent) + case 0x3f: memoryRead(); swi3(); break; // SWI (SWI3 inherent) default: UNREACHABLE; @@ -632,7 +669,9 @@ EightBit::register16_t& EightBit::mc6809::RR(const int which) { } EightBit::register16_t EightBit::mc6809::Address_relative_byte() { - return PC() + (int8_t)fetchByte(); + const auto address = PC() + (int8_t)fetchByte(); + memoryRead(0xffff); + return address; } EightBit::register16_t EightBit::mc6809::Address_relative_word() { @@ -640,7 +679,9 @@ EightBit::register16_t EightBit::mc6809::Address_relative_word() { } EightBit::register16_t EightBit::mc6809::Address_direct() { - return register16_t(fetchByte(), DP()); + const auto offset = fetchByte(); + memoryRead(0xffff); + return register16_t(offset, DP()); } EightBit::register16_t EightBit::mc6809::Address_indexed() { @@ -653,77 +694,100 @@ EightBit::register16_t EightBit::mc6809::Address_indexed() { switch (type & Mask4) { case 0b0000: // ,R+ ASSUME(!indirect); - tick(2); address = r++; + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b0001: // ,R++ - tick(3); address = r; r += 2; + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b0010: // ,-R ASSUME(!indirect); - tick(2); address = --r; + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b0011: // ,--R - tick(3); r -= 2; address = r; + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b0100: // ,R address = r; + memoryRead(); break; case 0b0101: // B,R - tick(1); address = r + (int8_t)B(); + memoryRead(PC()); + memoryRead(0xffff); break; case 0b0110: // A,R - tick(1); address = r + (int8_t)A(); + memoryRead(PC()); + memoryRead(0xffff); break; case 0b1000: // n,R (eight-bit) - tick(1); address = r + (int8_t)fetchByte(); + memoryRead(0xffff); break; case 0b1001: // n,R (sixteen-bit) - tick(4); address = r + (int16_t)fetchWord().word; + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b1011: // D,R - tick(4); address = r + D(); + memoryRead(PC()); + memoryRead(PC() + 1); + memoryRead(PC() + 2); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b1100: // n,PCR (eight-bit) - tick(1); address = Address_relative_byte(); break; case 0b1101: // n,PCR (sixteen-bit) - tick(2); address = Address_relative_word(); + memoryRead(PC()); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); break; case 0b1111: // [n] assert(indirect); - tick(2); address = Address_extended(); + memoryRead(PC()); break; default: UNREACHABLE; } if (indirect) { - tick(3); address = Processor::getWord(address); + memoryRead(0xffff); } } else { // EA = ,R + 5-bit offset - tick(); address = r + signExtend(5, type & Mask5); + memoryRead(0xffff); } return address; } EightBit::register16_t EightBit::mc6809::Address_extended() { - return fetchWord(); + const auto ea = fetchWord(); + memoryRead(0xffff); + return ea; } // @@ -797,6 +861,7 @@ uint8_t EightBit::mc6809::add(const uint8_t operand, const uint8_t data, const u EightBit::register16_t EightBit::mc6809::add(const register16_t operand, const register16_t data) { const uint32_t addition = operand.word + data.word; adjustAddition(operand, data, addition); + memoryRead(0xffff); return addition & Mask16; } @@ -823,7 +888,7 @@ void EightBit::mc6809::bit(const uint8_t operand, const uint8_t data) { andr(operand, data); } -uint8_t EightBit::mc6809::clr() { +uint8_t EightBit::mc6809::clr(uint8_t) { CC() = clearBit(CC(), CF); return through((uint8_t)0U); } @@ -843,6 +908,8 @@ uint8_t EightBit::mc6809::com(const uint8_t operand) { void EightBit::mc6809::cwai(const uint8_t data) { CC() &= data; + memoryRead(PC()); + memoryRead(0xffff); saveEntireRegisterState(); halt(); } @@ -920,6 +987,13 @@ void EightBit::mc6809::exg(const uint8_t data) { std::swap(referenceTransfer8(reg1), referenceTransfer8(reg2)); else std::swap(referenceTransfer16(reg1), referenceTransfer16(reg2)); + + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); } uint8_t EightBit::mc6809::inc(uint8_t operand) { @@ -945,6 +1019,15 @@ EightBit::register16_t EightBit::mc6809::mul(const uint8_t first, const uint8_t const register16_t result = first * second; adjustZero(result); CC() = setBit(CC(), CF, result.low & Bit7); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); return result; } @@ -962,75 +1045,49 @@ uint8_t EightBit::mc6809::orr(const uint8_t operand, const uint8_t data) { } void EightBit::mc6809::psh(register16_t& stack, const uint8_t data) { - if (data & Bit7) { - tick(2); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(stack); + if (data & Bit7) pushWord(stack, PC()); - } - if (data & Bit6) { - tick(2); + if (data & Bit6) // Pushing to the S stack means we must be pushing U pushWord(stack, &stack == &S() ? U() : S()); - } - if (data & Bit5) { - tick(2); + if (data & Bit5) pushWord(stack, Y()); - } - if (data & Bit4) { - tick(2); + if (data & Bit4) pushWord(stack, X()); - } - if (data & Bit3) { - tick(); + if (data & Bit3) push(stack, DP()); - } - if (data & Bit2) { - tick(); + if (data & Bit2) push(stack, B()); - } - if (data & Bit1) { - tick(); + if (data & Bit1) push(stack, A()); - } - if (data & Bit0) { - tick(); + if (data & Bit0) push(stack, CC()); - } } void EightBit::mc6809::pul(register16_t& stack, const uint8_t data) { - if (data & Bit0) { - tick(); + memoryRead(0xffff); + memoryRead(0xffff); + if (data & Bit0) CC() = pop(stack); - } - if (data & Bit1) { - tick(); + if (data & Bit1) A() = pop(stack); - } - if (data & Bit2) { - tick(); + if (data & Bit2) B() = pop(stack); - } - if (data & Bit3) { - tick(); + if (data & Bit3) DP() = pop(stack); - } - if (data & Bit4) { - tick(2); + if (data & Bit4) X() = popWord(stack); - } - if (data & Bit5) { - tick(2); + if (data & Bit5) Y() = popWord(stack); - } - if (data & Bit6) { - tick(2); + if (data & Bit6) // Pulling from the S stack means we must be pulling U (&stack == &S() ? U() : S()) = popWord(stack); - } - if (data & Bit7) { - tick(2); + if (data & Bit7) PC() = popWord(stack); - } + memoryRead(stack); } uint8_t EightBit::mc6809::rol(const uint8_t operand) { @@ -1052,27 +1109,35 @@ uint8_t EightBit::mc6809::ror(const uint8_t operand) { void EightBit::mc6809::rti() { restoreRegisterState(); + memoryRead(0xffff); } void EightBit::mc6809::rts() { ret(); + memoryRead(0xffff); } void EightBit::mc6809::swi() { + memoryRead(0xffff); saveEntireRegisterState(); CC() = setBit(CC(), IF); // Disable IRQ CC() = setBit(CC(), FF); // Disable FIRQ jump(getWordPaged(0xff, SWIvector)); + memoryRead(0xffff); } void EightBit::mc6809::swi2() { + memoryRead(0xffff); saveEntireRegisterState(); jump(getWordPaged(0xff, SWI2vector)); + memoryRead(0xffff); } void EightBit::mc6809::swi3() { + memoryRead(0xffff); saveEntireRegisterState(); jump(getWordPaged(0xff, SWI3vector)); + memoryRead(0xffff); } uint8_t EightBit::mc6809::sex(const uint8_t from) { @@ -1092,6 +1157,11 @@ void EightBit::mc6809::tfr(const uint8_t data) { referenceTransfer8(reg2) = referenceTransfer8(reg1); else referenceTransfer16(reg2) = referenceTransfer16(reg1); + + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); + memoryRead(0xffff); } uint8_t EightBit::mc6809::sbc(const uint8_t operand, const uint8_t data) { @@ -1107,6 +1177,7 @@ uint8_t EightBit::mc6809::sub(const uint8_t operand, const uint8_t data, const u EightBit::register16_t EightBit::mc6809::sub(const register16_t operand, const register16_t data) { const uint32_t subtraction = operand.word - data.word; adjustSubtraction(operand, data, subtraction); + memoryRead(0xffff); return subtraction & Mask16; } diff --git a/MC6809/unittest/mc6809_tests.cpp b/MC6809/unittest/mc6809_tests.cpp index ee2f111..d3a9ab6 100644 --- a/MC6809/unittest/mc6809_tests.cpp +++ b/MC6809/unittest/mc6809_tests.cpp @@ -655,7 +655,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S REQUIRE((cpu.CC() & EightBit::mc6809::VF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::NF) != 0); REQUIRE((cpu.CC() & EightBit::mc6809::CF) != 0); - REQUIRE(cpu.cycles() == 4); + REQUIRE(cpu.cycles() == 2); } // Test the subtraction with carry instruction. @@ -691,7 +691,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S REQUIRE((cpu.CC() & EightBit::mc6809::VF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::ZF) != 0); REQUIRE((cpu.CC() & EightBit::mc6809::NF) == 0); - REQUIRE(cpu.cycles() == 4); + REQUIRE(cpu.cycles() == 2); } // Test the SBCA instruction. @@ -707,7 +707,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S REQUIRE((cpu.CC() & EightBit::mc6809::VF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::ZF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::NF) == 0); - REQUIRE(cpu.cycles() == 4); + REQUIRE(cpu.cycles() == 2); } // Test the SBCA instruction. @@ -722,7 +722,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S REQUIRE((cpu.CC() & EightBit::mc6809::VF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::ZF) == 0); REQUIRE((cpu.CC() & EightBit::mc6809::NF) != 0); - REQUIRE(cpu.cycles() == 4); + REQUIRE(cpu.cycles() == 2); } } @@ -935,7 +935,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") { SECTION("BLE1") { cpu.A() = 0; - cpu.CC() = EightBit::mc6809::ZF; + cpu.CC() = EightBit::mc6809::ZF; cpu.step(); cpu.step(); REQUIRE(cpu.A() == 2); @@ -984,9 +984,14 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") { cpu.step(); REQUIRE(cpu.A() == 2); } +} - cpu.lowerRESET(); - cpu.step(); +TEST_CASE("Subroutines", "[JSR][RTS]") { + + Board board; + board.raisePOWER(); + auto& cpu = board.CPU(); + cpu.step(); // Step over the reset // Test the JSR - Jump to Subroutine - instruction. // INDEXED mode: JSR D,Y @@ -1029,7 +1034,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") { REQUIRE(board.peek(0x914) == 2); REQUIRE(board.peek(0x913) == 0xb); - REQUIRE(cpu.cycles() == 10); + REQUIRE(cpu.cycles() == 11); } cpu.lowerRESET();