diff options
Diffstat (limited to 'src/devices/cpu/m6800/m6801.cpp')
-rw-r--r-- | src/devices/cpu/m6800/m6801.cpp | 2503 |
1 files changed, 1905 insertions, 598 deletions
diff --git a/src/devices/cpu/m6800/m6801.cpp b/src/devices/cpu/m6800/m6801.cpp index 28339b33005..e289a5544ba 100644 --- a/src/devices/cpu/m6800/m6801.cpp +++ b/src/devices/cpu/m6800/m6801.cpp @@ -1,18 +1,42 @@ // license:BSD-3-Clause // copyright-holders:Aaron Giles +/* + +6801 and derivatives + +TODO: +- improve serial emulation: receiver listens to start bit at 8*data rate, + and will start reading 1.5 'bits' after the start bit +- improve RAM control register +- improve STBY pin? RES pin (reset) should be ineffective while STBY is low +- IS3 interrupt for 6801 port 3 handshake (already implemented for 6301Y) +- address TRAP (at the moment, only illegal opcode TRAP is emulated) + if PC directed these areas: + 'mode' is selected by the sense of p2.0,p2.1,and p2.3 at reset timing. + mode 0,1,2,4,6 : $0000-$001f + mode 5 : $0000-$001f,$0200-$efff + mode 7 : $0000-$001f,$0100-$efff +- finish 6301Y port 6 handshake, share implementation with p3csr? +- 6301Y sci_trcsr2_r/w +- 6801U4 tcr1_r/w + +*/ #include "emu.h" -#include "cpu/m6800/m6801.h" +#include "m6801.h" +#include "6800dasm.h" + +#include <tuple> -#define LOG_GENERAL (1U << 0) #define LOG_TX (1U << 1) #define LOG_TXTICK (1U << 2) #define LOG_RX (1U << 3) #define LOG_RXTICK (1U << 4) #define LOG_PORT (1U << 5) +#define LOG_SER (1U << 6) +#define LOG_TIMER (1U << 7) -//#define VERBOSE (LOG_GENERAL | LOG_TX | LOG_RX | LOG_PORT) -//#define LOG_OUTPUT_STREAM std::cerr +//#define VERBOSE (LOG_PORT) #include "logmacro.h" #define LOGTX(...) LOGMASKED(LOG_TX, __VA_ARGS__) @@ -20,69 +44,25 @@ #define LOGRX(...) LOGMASKED(LOG_RX, __VA_ARGS__) #define LOGRXTICK(...) LOGMASKED(LOG_RXTICK, __VA_ARGS__) #define LOGPORT(...) LOGMASKED(LOG_PORT, __VA_ARGS__) +#define LOGSER(...) LOGMASKED(LOG_SER, __VA_ARGS__) +#define LOGTIMER(...) LOGMASKED(LOG_TIMER, __VA_ARGS__) #define CT m_counter.w.l #define CTH m_counter.w.h #define CTD m_counter.d -#define OC m_output_compare.w.l -#define OCH m_output_compare.w.h -#define OCD m_output_compare.d -#define TOH m_timer_over.w.l +#define OC m_output_compare[0].w.l +#define OCH m_output_compare[0].w.h +#define OCD m_output_compare[0].d +#define OC2 m_output_compare[1].w.l +#define OC2H m_output_compare[1].w.h +#define OC2D m_output_compare[1].d +#define OC3 m_output_compare[2].w.l +#define OC3H m_output_compare[2].w.h +#define OC3D m_output_compare[2].d +#define TOH m_timer_over.w.h #define TOD m_timer_over.d -#define MODIFIED_tcsr { \ - m_irq2 = (m_tcsr&(m_tcsr<<3))&(TCSR_ICF|TCSR_OCF|TCSR_TOF); \ -} - -#define SET_TIMER_EVENT { \ - m_timer_next = (OCD - CTD < TOD - CTD) ? OCD : TOD; \ -} - -/* when change freerunningcounter or outputcapture */ -#define MODIFIED_counters { \ - OCH = (OC >= CT) ? CTH : CTH+1; \ - SET_TIMER_EVENT; \ -} - -// I/O registers - -enum -{ - IO_P1DDR = 0, - IO_P2DDR, - IO_P1DATA, - IO_P2DATA, - IO_P3DDR, - IO_P4DDR, - IO_P3DATA, - IO_P4DATA, - IO_TCSR, - IO_CH, - IO_CL, - IO_OCRH, - IO_OCRL, - IO_ICRH, - IO_ICRL, - IO_P3CSR, - IO_RMCR, - IO_TRCSR, - IO_RDR, - IO_TDR, - IO_RCR, - IO_CAAH, - IO_CAAL, - IO_TCR1, - IO_TCR2, - IO_TSR, - IO_OCR2H, - IO_OCR2L, - IO_OCR3H, - IO_OCR3L, - IO_ICR2H, - IO_ICR2L -}; - // serial I/O #define M6801_RMCR_SS_MASK 0x03 // Speed Select @@ -120,26 +100,40 @@ enum M6801_TX_STATE_READY }; -/* take interrupt */ -#define TAKE_ICI enter_interrupt("take ICI\n",0xfff6) -#define TAKE_OCI enter_interrupt("take OCI\n",0xfff4) -#define TAKE_TOI enter_interrupt("take TOI\n",0xfff2) -#define TAKE_SCI enter_interrupt("take SCI\n",0xfff0) - -/* mnemonicos for the Timer Control and Status Register bits */ -#define TCSR_OLVL 0x01 -#define TCSR_IEDG 0x02 -#define TCSR_ETOI 0x04 -#define TCSR_EOCI 0x08 -#define TCSR_EICI 0x10 -#define TCSR_TOF 0x20 -#define TCSR_OCF 0x40 -#define TCSR_ICF 0x80 - -/* Note: don't use 0 cycles here for invalid opcodes so that we don't */ -/* hang in an infinite loop if we hit one */ -#define XX 5 // invalid opcode unknown cc -const uint8_t m6801_cpu_device::cycles_6803[256] = +/* mnemonics for the Timer Control and Status Register bits */ +#define TCSR_OLVL 0x01 +#define TCSR_IEDG 0x02 +#define TCSR_ETOI 0x04 +#define TCSR_EOCI 0x08 +#define TCSR_EICI 0x10 +#define TCSR_TOF 0x20 +#define TCSR_OCF 0x40 +#define TCSR_ICF 0x80 + +#define TCSR2_OE1 0x01 +#define TCSR2_OE2 0x02 +#define TCSR2_OLVL2 0x04 +#define TCSR2_EOCI2 0x08 +#define TCSR2_OCF2 0x20 + +#define TCR2_ETOI 0x04 +#define TCR2_EOCI1 0x08 +#define TCR2_EOCI2 0x10 +#define TCR2_EOCI3 0x20 +#define TCR2_EICI1 0x40 +#define TCR2_EICI2 0x80 + +#define TSR_TOF 0x04 +#define TSR_OCF1 0x08 +#define TSR_OCF2 0x10 +#define TSR_OCF3 0x20 +#define TSR_ICF1 0x40 +#define TSR_ICF2 0x80 + +// to prevent the possibility of MAME locking up, don't use 0 cycles here +#define XX 4 // illegal opcode unknown cycle count + +const u8 m6801_cpu_device::cycles_6803[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /*0*/ XX, 2,XX,XX, 3, 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, @@ -160,7 +154,7 @@ const uint8_t m6801_cpu_device::cycles_6803[256] = /*F*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 }; -const uint8_t m6801_cpu_device::cycles_63701[256] = +const u8 m6801_cpu_device::cycles_63701[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /*0*/ XX, 1,XX,XX, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -171,213 +165,694 @@ const uint8_t m6801_cpu_device::cycles_63701[256] = /*5*/ 1,XX,XX, 1, 1,XX, 1, 1, 1, 1, 1,XX, 1, 1,XX, 1, /*6*/ 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 4, 3, 5, /*7*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 3, 5, - /*8*/ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 5, 3, 3, + /*8*/ 2, 2, 2, 3, 2, 2, 2,XX, 2, 2, 2, 2, 3, 5, 3,XX, /*9*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4, /*A*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, /*B*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, - /*C*/ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3,XX, 3, 3, + /*C*/ 2, 2, 2, 3, 2, 2, 2,XX, 2, 2, 2, 2, 3,XX, 3,XX, /*D*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, /*E*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, /*F*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 }; -#undef XX // /invalid opcode unknown cc + +#undef XX // /illegal opcode unknown cc const m6800_cpu_device::op_func m6801_cpu_device::m6803_insn[0x100] = { -&m6801_cpu_device::illegl1,&m6801_cpu_device::nop, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::lsrd, &m6801_cpu_device::asld, &m6801_cpu_device::tap, &m6801_cpu_device::tpa, +// 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F +&m6801_cpu_device::illegl1,&m6801_cpu_device::nop, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::lsrd, &m6801_cpu_device::asld, &m6801_cpu_device::tap, &m6801_cpu_device::tpa, // 0 &m6801_cpu_device::inx, &m6801_cpu_device::dex, &m6801_cpu_device::clv, &m6801_cpu_device::sev, &m6801_cpu_device::clc, &m6801_cpu_device::sec, &m6801_cpu_device::cli, &m6801_cpu_device::sei, -&m6801_cpu_device::sba, &m6801_cpu_device::cba, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::tab, &m6801_cpu_device::tba, +&m6801_cpu_device::sba, &m6801_cpu_device::cba, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::tab, &m6801_cpu_device::tba, // 1 &m6801_cpu_device::illegl1,&m6801_cpu_device::daa, &m6801_cpu_device::illegl1,&m6801_cpu_device::aba, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1, -&m6801_cpu_device::bra, &m6801_cpu_device::brn, &m6801_cpu_device::bhi, &m6801_cpu_device::bls, &m6801_cpu_device::bcc, &m6801_cpu_device::bcs, &m6801_cpu_device::bne, &m6801_cpu_device::beq, +&m6801_cpu_device::bra, &m6801_cpu_device::brn, &m6801_cpu_device::bhi, &m6801_cpu_device::bls, &m6801_cpu_device::bcc, &m6801_cpu_device::bcs, &m6801_cpu_device::bne, &m6801_cpu_device::beq, // 2 &m6801_cpu_device::bvc, &m6801_cpu_device::bvs, &m6801_cpu_device::bpl, &m6801_cpu_device::bmi, &m6801_cpu_device::bge, &m6801_cpu_device::blt, &m6801_cpu_device::bgt, &m6801_cpu_device::ble, -&m6801_cpu_device::tsx, &m6801_cpu_device::ins, &m6801_cpu_device::pula, &m6801_cpu_device::pulb, &m6801_cpu_device::des, &m6801_cpu_device::txs, &m6801_cpu_device::psha, &m6801_cpu_device::pshb, +&m6801_cpu_device::tsx, &m6801_cpu_device::ins, &m6801_cpu_device::pula, &m6801_cpu_device::pulb, &m6801_cpu_device::des, &m6801_cpu_device::txs, &m6801_cpu_device::psha, &m6801_cpu_device::pshb, // 3 &m6801_cpu_device::pulx, &m6801_cpu_device::rts, &m6801_cpu_device::abx, &m6801_cpu_device::rti, &m6801_cpu_device::pshx, &m6801_cpu_device::mul, &m6801_cpu_device::wai, &m6801_cpu_device::swi, -&m6801_cpu_device::nega, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::coma, &m6801_cpu_device::lsra, &m6801_cpu_device::illegl1,&m6801_cpu_device::rora, &m6801_cpu_device::asra, +&m6801_cpu_device::nega, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::coma, &m6801_cpu_device::lsra, &m6801_cpu_device::illegl1,&m6801_cpu_device::rora, &m6801_cpu_device::asra, // 4 &m6801_cpu_device::asla, &m6801_cpu_device::rola, &m6801_cpu_device::deca, &m6801_cpu_device::illegl1,&m6801_cpu_device::inca, &m6801_cpu_device::tsta, &m6801_cpu_device::illegl1,&m6801_cpu_device::clra, -&m6801_cpu_device::negb, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::comb, &m6801_cpu_device::lsrb, &m6801_cpu_device::illegl1,&m6801_cpu_device::rorb, &m6801_cpu_device::asrb, +&m6801_cpu_device::negb, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::comb, &m6801_cpu_device::lsrb, &m6801_cpu_device::illegl1,&m6801_cpu_device::rorb, &m6801_cpu_device::asrb, // 5 &m6801_cpu_device::aslb, &m6801_cpu_device::rolb, &m6801_cpu_device::decb, &m6801_cpu_device::illegl1,&m6801_cpu_device::incb, &m6801_cpu_device::tstb, &m6801_cpu_device::illegl1,&m6801_cpu_device::clrb, -&m6801_cpu_device::neg_ix, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::com_ix, &m6801_cpu_device::lsr_ix, &m6801_cpu_device::illegl1,&m6801_cpu_device::ror_ix, &m6801_cpu_device::asr_ix, +&m6801_cpu_device::neg_ix, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::com_ix, &m6801_cpu_device::lsr_ix, &m6801_cpu_device::illegl1,&m6801_cpu_device::ror_ix, &m6801_cpu_device::asr_ix, // 6 &m6801_cpu_device::asl_ix, &m6801_cpu_device::rol_ix, &m6801_cpu_device::dec_ix, &m6801_cpu_device::illegl1,&m6801_cpu_device::inc_ix, &m6801_cpu_device::tst_ix, &m6801_cpu_device::jmp_ix, &m6801_cpu_device::clr_ix, -&m6801_cpu_device::neg_ex, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::com_ex, &m6801_cpu_device::lsr_ex, &m6801_cpu_device::illegl1,&m6801_cpu_device::ror_ex, &m6801_cpu_device::asr_ex, +&m6801_cpu_device::neg_ex, &m6801_cpu_device::illegl1,&m6801_cpu_device::illegl1,&m6801_cpu_device::com_ex, &m6801_cpu_device::lsr_ex, &m6801_cpu_device::illegl1,&m6801_cpu_device::ror_ex, &m6801_cpu_device::asr_ex, // 7 &m6801_cpu_device::asl_ex, &m6801_cpu_device::rol_ex, &m6801_cpu_device::dec_ex, &m6801_cpu_device::illegl1,&m6801_cpu_device::inc_ex, &m6801_cpu_device::tst_ex, &m6801_cpu_device::jmp_ex, &m6801_cpu_device::clr_ex, -&m6801_cpu_device::suba_im,&m6801_cpu_device::cmpa_im,&m6801_cpu_device::sbca_im,&m6801_cpu_device::subd_im,&m6801_cpu_device::anda_im,&m6801_cpu_device::bita_im,&m6801_cpu_device::lda_im, &m6801_cpu_device::sta_im, +&m6801_cpu_device::suba_im,&m6801_cpu_device::cmpa_im,&m6801_cpu_device::sbca_im,&m6801_cpu_device::subd_im,&m6801_cpu_device::anda_im,&m6801_cpu_device::bita_im,&m6801_cpu_device::lda_im, &m6801_cpu_device::sta_im, // 8 &m6801_cpu_device::eora_im,&m6801_cpu_device::adca_im,&m6801_cpu_device::ora_im, &m6801_cpu_device::adda_im,&m6801_cpu_device::cpx_im ,&m6801_cpu_device::bsr, &m6801_cpu_device::lds_im, &m6801_cpu_device::sts_im, -&m6801_cpu_device::suba_di,&m6801_cpu_device::cmpa_di,&m6801_cpu_device::sbca_di,&m6801_cpu_device::subd_di,&m6801_cpu_device::anda_di,&m6801_cpu_device::bita_di,&m6801_cpu_device::lda_di, &m6801_cpu_device::sta_di, +&m6801_cpu_device::suba_di,&m6801_cpu_device::cmpa_di,&m6801_cpu_device::sbca_di,&m6801_cpu_device::subd_di,&m6801_cpu_device::anda_di,&m6801_cpu_device::bita_di,&m6801_cpu_device::lda_di, &m6801_cpu_device::sta_di, // 9 &m6801_cpu_device::eora_di,&m6801_cpu_device::adca_di,&m6801_cpu_device::ora_di, &m6801_cpu_device::adda_di,&m6801_cpu_device::cpx_di ,&m6801_cpu_device::jsr_di, &m6801_cpu_device::lds_di, &m6801_cpu_device::sts_di, -&m6801_cpu_device::suba_ix,&m6801_cpu_device::cmpa_ix,&m6801_cpu_device::sbca_ix,&m6801_cpu_device::subd_ix,&m6801_cpu_device::anda_ix,&m6801_cpu_device::bita_ix,&m6801_cpu_device::lda_ix, &m6801_cpu_device::sta_ix, +&m6801_cpu_device::suba_ix,&m6801_cpu_device::cmpa_ix,&m6801_cpu_device::sbca_ix,&m6801_cpu_device::subd_ix,&m6801_cpu_device::anda_ix,&m6801_cpu_device::bita_ix,&m6801_cpu_device::lda_ix, &m6801_cpu_device::sta_ix, // A &m6801_cpu_device::eora_ix,&m6801_cpu_device::adca_ix,&m6801_cpu_device::ora_ix, &m6801_cpu_device::adda_ix,&m6801_cpu_device::cpx_ix ,&m6801_cpu_device::jsr_ix, &m6801_cpu_device::lds_ix, &m6801_cpu_device::sts_ix, -&m6801_cpu_device::suba_ex,&m6801_cpu_device::cmpa_ex,&m6801_cpu_device::sbca_ex,&m6801_cpu_device::subd_ex,&m6801_cpu_device::anda_ex,&m6801_cpu_device::bita_ex,&m6801_cpu_device::lda_ex, &m6801_cpu_device::sta_ex, +&m6801_cpu_device::suba_ex,&m6801_cpu_device::cmpa_ex,&m6801_cpu_device::sbca_ex,&m6801_cpu_device::subd_ex,&m6801_cpu_device::anda_ex,&m6801_cpu_device::bita_ex,&m6801_cpu_device::lda_ex, &m6801_cpu_device::sta_ex, // B &m6801_cpu_device::eora_ex,&m6801_cpu_device::adca_ex,&m6801_cpu_device::ora_ex, &m6801_cpu_device::adda_ex,&m6801_cpu_device::cpx_ex ,&m6801_cpu_device::jsr_ex, &m6801_cpu_device::lds_ex, &m6801_cpu_device::sts_ex, -&m6801_cpu_device::subb_im,&m6801_cpu_device::cmpb_im,&m6801_cpu_device::sbcb_im,&m6801_cpu_device::addd_im,&m6801_cpu_device::andb_im,&m6801_cpu_device::bitb_im,&m6801_cpu_device::ldb_im, &m6801_cpu_device::stb_im, +&m6801_cpu_device::subb_im,&m6801_cpu_device::cmpb_im,&m6801_cpu_device::sbcb_im,&m6801_cpu_device::addd_im,&m6801_cpu_device::andb_im,&m6801_cpu_device::bitb_im,&m6801_cpu_device::ldb_im, &m6801_cpu_device::stb_im, // C &m6801_cpu_device::eorb_im,&m6801_cpu_device::adcb_im,&m6801_cpu_device::orb_im, &m6801_cpu_device::addb_im,&m6801_cpu_device::ldd_im, &m6801_cpu_device::std_im, &m6801_cpu_device::ldx_im, &m6801_cpu_device::stx_im, -&m6801_cpu_device::subb_di,&m6801_cpu_device::cmpb_di,&m6801_cpu_device::sbcb_di,&m6801_cpu_device::addd_di,&m6801_cpu_device::andb_di,&m6801_cpu_device::bitb_di,&m6801_cpu_device::ldb_di, &m6801_cpu_device::stb_di, +&m6801_cpu_device::subb_di,&m6801_cpu_device::cmpb_di,&m6801_cpu_device::sbcb_di,&m6801_cpu_device::addd_di,&m6801_cpu_device::andb_di,&m6801_cpu_device::bitb_di,&m6801_cpu_device::ldb_di, &m6801_cpu_device::stb_di, // D &m6801_cpu_device::eorb_di,&m6801_cpu_device::adcb_di,&m6801_cpu_device::orb_di, &m6801_cpu_device::addb_di,&m6801_cpu_device::ldd_di, &m6801_cpu_device::std_di, &m6801_cpu_device::ldx_di, &m6801_cpu_device::stx_di, -&m6801_cpu_device::subb_ix,&m6801_cpu_device::cmpb_ix,&m6801_cpu_device::sbcb_ix,&m6801_cpu_device::addd_ix,&m6801_cpu_device::andb_ix,&m6801_cpu_device::bitb_ix,&m6801_cpu_device::ldb_ix, &m6801_cpu_device::stb_ix, +&m6801_cpu_device::subb_ix,&m6801_cpu_device::cmpb_ix,&m6801_cpu_device::sbcb_ix,&m6801_cpu_device::addd_ix,&m6801_cpu_device::andb_ix,&m6801_cpu_device::bitb_ix,&m6801_cpu_device::ldb_ix, &m6801_cpu_device::stb_ix, // E &m6801_cpu_device::eorb_ix,&m6801_cpu_device::adcb_ix,&m6801_cpu_device::orb_ix, &m6801_cpu_device::addb_ix,&m6801_cpu_device::ldd_ix, &m6801_cpu_device::std_ix, &m6801_cpu_device::ldx_ix, &m6801_cpu_device::stx_ix, -&m6801_cpu_device::subb_ex,&m6801_cpu_device::cmpb_ex,&m6801_cpu_device::sbcb_ex,&m6801_cpu_device::addd_ex,&m6801_cpu_device::andb_ex,&m6801_cpu_device::bitb_ex,&m6801_cpu_device::ldb_ex, &m6801_cpu_device::stb_ex, +&m6801_cpu_device::subb_ex,&m6801_cpu_device::cmpb_ex,&m6801_cpu_device::sbcb_ex,&m6801_cpu_device::addd_ex,&m6801_cpu_device::andb_ex,&m6801_cpu_device::bitb_ex,&m6801_cpu_device::ldb_ex, &m6801_cpu_device::stb_ex, // F &m6801_cpu_device::eorb_ex,&m6801_cpu_device::adcb_ex,&m6801_cpu_device::orb_ex, &m6801_cpu_device::addb_ex,&m6801_cpu_device::ldd_ex, &m6801_cpu_device::std_ex, &m6801_cpu_device::ldx_ex, &m6801_cpu_device::stx_ex }; const m6800_cpu_device::op_func m6801_cpu_device::hd63701_insn[0x100] = { -&m6801_cpu_device::trap, &m6801_cpu_device::nop, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::lsrd, &m6801_cpu_device::asld, &m6801_cpu_device::tap, &m6801_cpu_device::tpa, +// 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F +&m6801_cpu_device::trap, &m6801_cpu_device::nop, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::lsrd, &m6801_cpu_device::asld, &m6801_cpu_device::tap, &m6801_cpu_device::tpa, // 0 &m6801_cpu_device::inx, &m6801_cpu_device::dex, &m6801_cpu_device::clv, &m6801_cpu_device::sev, &m6801_cpu_device::clc, &m6801_cpu_device::sec, &m6801_cpu_device::cli, &m6801_cpu_device::sei, -&m6801_cpu_device::sba, &m6801_cpu_device::cba, &m6801_cpu_device::undoc1, &m6801_cpu_device::undoc2, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::tab, &m6801_cpu_device::tba, +&m6801_cpu_device::sba, &m6801_cpu_device::cba, &m6801_cpu_device::undoc1, &m6801_cpu_device::undoc2, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::tab, &m6801_cpu_device::tba, // 1 &m6801_cpu_device::xgdx, &m6801_cpu_device::daa, &m6801_cpu_device::slp, &m6801_cpu_device::aba, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::trap, -&m6801_cpu_device::bra, &m6801_cpu_device::brn, &m6801_cpu_device::bhi, &m6801_cpu_device::bls, &m6801_cpu_device::bcc, &m6801_cpu_device::bcs, &m6801_cpu_device::bne, &m6801_cpu_device::beq, +&m6801_cpu_device::bra, &m6801_cpu_device::brn, &m6801_cpu_device::bhi, &m6801_cpu_device::bls, &m6801_cpu_device::bcc, &m6801_cpu_device::bcs, &m6801_cpu_device::bne, &m6801_cpu_device::beq, // 2 &m6801_cpu_device::bvc, &m6801_cpu_device::bvs, &m6801_cpu_device::bpl, &m6801_cpu_device::bmi, &m6801_cpu_device::bge, &m6801_cpu_device::blt, &m6801_cpu_device::bgt, &m6801_cpu_device::ble, -&m6801_cpu_device::tsx, &m6801_cpu_device::ins, &m6801_cpu_device::pula, &m6801_cpu_device::pulb, &m6801_cpu_device::des, &m6801_cpu_device::txs, &m6801_cpu_device::psha, &m6801_cpu_device::pshb, +&m6801_cpu_device::tsx, &m6801_cpu_device::ins, &m6801_cpu_device::pula, &m6801_cpu_device::pulb, &m6801_cpu_device::des, &m6801_cpu_device::txs, &m6801_cpu_device::psha, &m6801_cpu_device::pshb, // 3 &m6801_cpu_device::pulx, &m6801_cpu_device::rts, &m6801_cpu_device::abx, &m6801_cpu_device::rti, &m6801_cpu_device::pshx, &m6801_cpu_device::mul, &m6801_cpu_device::wai, &m6801_cpu_device::swi, -&m6801_cpu_device::nega, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::coma, &m6801_cpu_device::lsra, &m6801_cpu_device::trap, &m6801_cpu_device::rora, &m6801_cpu_device::asra, +&m6801_cpu_device::nega, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::coma, &m6801_cpu_device::lsra, &m6801_cpu_device::trap, &m6801_cpu_device::rora, &m6801_cpu_device::asra, // 4 &m6801_cpu_device::asla, &m6801_cpu_device::rola, &m6801_cpu_device::deca, &m6801_cpu_device::trap, &m6801_cpu_device::inca, &m6801_cpu_device::tsta, &m6801_cpu_device::trap, &m6801_cpu_device::clra, -&m6801_cpu_device::negb, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::comb, &m6801_cpu_device::lsrb, &m6801_cpu_device::trap, &m6801_cpu_device::rorb, &m6801_cpu_device::asrb, +&m6801_cpu_device::negb, &m6801_cpu_device::trap, &m6801_cpu_device::trap, &m6801_cpu_device::comb, &m6801_cpu_device::lsrb, &m6801_cpu_device::trap, &m6801_cpu_device::rorb, &m6801_cpu_device::asrb, // 5 &m6801_cpu_device::aslb, &m6801_cpu_device::rolb, &m6801_cpu_device::decb, &m6801_cpu_device::trap, &m6801_cpu_device::incb, &m6801_cpu_device::tstb, &m6801_cpu_device::trap, &m6801_cpu_device::clrb, -&m6801_cpu_device::neg_ix, &m6801_cpu_device::aim_ix, &m6801_cpu_device::oim_ix, &m6801_cpu_device::com_ix, &m6801_cpu_device::lsr_ix, &m6801_cpu_device::eim_ix, &m6801_cpu_device::ror_ix, &m6801_cpu_device::asr_ix, +&m6801_cpu_device::neg_ix, &m6801_cpu_device::aim_ix, &m6801_cpu_device::oim_ix, &m6801_cpu_device::com_ix, &m6801_cpu_device::lsr_ix, &m6801_cpu_device::eim_ix, &m6801_cpu_device::ror_ix, &m6801_cpu_device::asr_ix, // 6 &m6801_cpu_device::asl_ix, &m6801_cpu_device::rol_ix, &m6801_cpu_device::dec_ix, &m6801_cpu_device::tim_ix, &m6801_cpu_device::inc_ix, &m6801_cpu_device::tst_ix, &m6801_cpu_device::jmp_ix, &m6801_cpu_device::clr_ix, -&m6801_cpu_device::neg_ex, &m6801_cpu_device::aim_di, &m6801_cpu_device::oim_di, &m6801_cpu_device::com_ex, &m6801_cpu_device::lsr_ex, &m6801_cpu_device::eim_di, &m6801_cpu_device::ror_ex, &m6801_cpu_device::asr_ex, +&m6801_cpu_device::neg_ex, &m6801_cpu_device::aim_di, &m6801_cpu_device::oim_di, &m6801_cpu_device::com_ex, &m6801_cpu_device::lsr_ex, &m6801_cpu_device::eim_di, &m6801_cpu_device::ror_ex, &m6801_cpu_device::asr_ex, // 7 &m6801_cpu_device::asl_ex, &m6801_cpu_device::rol_ex, &m6801_cpu_device::dec_ex, &m6801_cpu_device::tim_di, &m6801_cpu_device::inc_ex, &m6801_cpu_device::tst_ex, &m6801_cpu_device::jmp_ex, &m6801_cpu_device::clr_ex, -&m6801_cpu_device::suba_im,&m6801_cpu_device::cmpa_im,&m6801_cpu_device::sbca_im,&m6801_cpu_device::subd_im,&m6801_cpu_device::anda_im,&m6801_cpu_device::bita_im,&m6801_cpu_device::lda_im, &m6801_cpu_device::sta_im, -&m6801_cpu_device::eora_im,&m6801_cpu_device::adca_im,&m6801_cpu_device::ora_im, &m6801_cpu_device::adda_im,&m6801_cpu_device::cpx_im ,&m6801_cpu_device::bsr, &m6801_cpu_device::lds_im, &m6801_cpu_device::sts_im, -&m6801_cpu_device::suba_di,&m6801_cpu_device::cmpa_di,&m6801_cpu_device::sbca_di,&m6801_cpu_device::subd_di,&m6801_cpu_device::anda_di,&m6801_cpu_device::bita_di,&m6801_cpu_device::lda_di, &m6801_cpu_device::sta_di, +&m6801_cpu_device::suba_im,&m6801_cpu_device::cmpa_im,&m6801_cpu_device::sbca_im,&m6801_cpu_device::subd_im,&m6801_cpu_device::anda_im,&m6801_cpu_device::bita_im,&m6801_cpu_device::lda_im, &m6801_cpu_device::trap, // 8 +&m6801_cpu_device::eora_im,&m6801_cpu_device::adca_im,&m6801_cpu_device::ora_im, &m6801_cpu_device::adda_im,&m6801_cpu_device::cpx_im ,&m6801_cpu_device::bsr, &m6801_cpu_device::lds_im, &m6801_cpu_device::trap, +&m6801_cpu_device::suba_di,&m6801_cpu_device::cmpa_di,&m6801_cpu_device::sbca_di,&m6801_cpu_device::subd_di,&m6801_cpu_device::anda_di,&m6801_cpu_device::bita_di,&m6801_cpu_device::lda_di, &m6801_cpu_device::sta_di, // 9 &m6801_cpu_device::eora_di,&m6801_cpu_device::adca_di,&m6801_cpu_device::ora_di, &m6801_cpu_device::adda_di,&m6801_cpu_device::cpx_di ,&m6801_cpu_device::jsr_di, &m6801_cpu_device::lds_di, &m6801_cpu_device::sts_di, -&m6801_cpu_device::suba_ix,&m6801_cpu_device::cmpa_ix,&m6801_cpu_device::sbca_ix,&m6801_cpu_device::subd_ix,&m6801_cpu_device::anda_ix,&m6801_cpu_device::bita_ix,&m6801_cpu_device::lda_ix, &m6801_cpu_device::sta_ix, +&m6801_cpu_device::suba_ix,&m6801_cpu_device::cmpa_ix,&m6801_cpu_device::sbca_ix,&m6801_cpu_device::subd_ix,&m6801_cpu_device::anda_ix,&m6801_cpu_device::bita_ix,&m6801_cpu_device::lda_ix, &m6801_cpu_device::sta_ix, // A &m6801_cpu_device::eora_ix,&m6801_cpu_device::adca_ix,&m6801_cpu_device::ora_ix, &m6801_cpu_device::adda_ix,&m6801_cpu_device::cpx_ix ,&m6801_cpu_device::jsr_ix, &m6801_cpu_device::lds_ix, &m6801_cpu_device::sts_ix, -&m6801_cpu_device::suba_ex,&m6801_cpu_device::cmpa_ex,&m6801_cpu_device::sbca_ex,&m6801_cpu_device::subd_ex,&m6801_cpu_device::anda_ex,&m6801_cpu_device::bita_ex,&m6801_cpu_device::lda_ex, &m6801_cpu_device::sta_ex, +&m6801_cpu_device::suba_ex,&m6801_cpu_device::cmpa_ex,&m6801_cpu_device::sbca_ex,&m6801_cpu_device::subd_ex,&m6801_cpu_device::anda_ex,&m6801_cpu_device::bita_ex,&m6801_cpu_device::lda_ex, &m6801_cpu_device::sta_ex, // B &m6801_cpu_device::eora_ex,&m6801_cpu_device::adca_ex,&m6801_cpu_device::ora_ex, &m6801_cpu_device::adda_ex,&m6801_cpu_device::cpx_ex ,&m6801_cpu_device::jsr_ex, &m6801_cpu_device::lds_ex, &m6801_cpu_device::sts_ex, -&m6801_cpu_device::subb_im,&m6801_cpu_device::cmpb_im,&m6801_cpu_device::sbcb_im,&m6801_cpu_device::addd_im,&m6801_cpu_device::andb_im,&m6801_cpu_device::bitb_im,&m6801_cpu_device::ldb_im, &m6801_cpu_device::stb_im, -&m6801_cpu_device::eorb_im,&m6801_cpu_device::adcb_im,&m6801_cpu_device::orb_im, &m6801_cpu_device::addb_im,&m6801_cpu_device::ldd_im, &m6801_cpu_device::std_im, &m6801_cpu_device::ldx_im, &m6801_cpu_device::stx_im, -&m6801_cpu_device::subb_di,&m6801_cpu_device::cmpb_di,&m6801_cpu_device::sbcb_di,&m6801_cpu_device::addd_di,&m6801_cpu_device::andb_di,&m6801_cpu_device::bitb_di,&m6801_cpu_device::ldb_di, &m6801_cpu_device::stb_di, +&m6801_cpu_device::subb_im,&m6801_cpu_device::cmpb_im,&m6801_cpu_device::sbcb_im,&m6801_cpu_device::addd_im,&m6801_cpu_device::andb_im,&m6801_cpu_device::bitb_im,&m6801_cpu_device::ldb_im, &m6801_cpu_device::trap, // C +&m6801_cpu_device::eorb_im,&m6801_cpu_device::adcb_im,&m6801_cpu_device::orb_im, &m6801_cpu_device::addb_im,&m6801_cpu_device::ldd_im, &m6801_cpu_device::trap, &m6801_cpu_device::ldx_im, &m6801_cpu_device::trap, +&m6801_cpu_device::subb_di,&m6801_cpu_device::cmpb_di,&m6801_cpu_device::sbcb_di,&m6801_cpu_device::addd_di,&m6801_cpu_device::andb_di,&m6801_cpu_device::bitb_di,&m6801_cpu_device::ldb_di, &m6801_cpu_device::stb_di, // D &m6801_cpu_device::eorb_di,&m6801_cpu_device::adcb_di,&m6801_cpu_device::orb_di, &m6801_cpu_device::addb_di,&m6801_cpu_device::ldd_di, &m6801_cpu_device::std_di, &m6801_cpu_device::ldx_di, &m6801_cpu_device::stx_di, -&m6801_cpu_device::subb_ix,&m6801_cpu_device::cmpb_ix,&m6801_cpu_device::sbcb_ix,&m6801_cpu_device::addd_ix,&m6801_cpu_device::andb_ix,&m6801_cpu_device::bitb_ix,&m6801_cpu_device::ldb_ix, &m6801_cpu_device::stb_ix, +&m6801_cpu_device::subb_ix,&m6801_cpu_device::cmpb_ix,&m6801_cpu_device::sbcb_ix,&m6801_cpu_device::addd_ix,&m6801_cpu_device::andb_ix,&m6801_cpu_device::bitb_ix,&m6801_cpu_device::ldb_ix, &m6801_cpu_device::stb_ix, // E &m6801_cpu_device::eorb_ix,&m6801_cpu_device::adcb_ix,&m6801_cpu_device::orb_ix, &m6801_cpu_device::addb_ix,&m6801_cpu_device::ldd_ix, &m6801_cpu_device::std_ix, &m6801_cpu_device::ldx_ix, &m6801_cpu_device::stx_ix, -&m6801_cpu_device::subb_ex,&m6801_cpu_device::cmpb_ex,&m6801_cpu_device::sbcb_ex,&m6801_cpu_device::addd_ex,&m6801_cpu_device::andb_ex,&m6801_cpu_device::bitb_ex,&m6801_cpu_device::ldb_ex, &m6801_cpu_device::stb_ex, +&m6801_cpu_device::subb_ex,&m6801_cpu_device::cmpb_ex,&m6801_cpu_device::sbcb_ex,&m6801_cpu_device::addd_ex,&m6801_cpu_device::andb_ex,&m6801_cpu_device::bitb_ex,&m6801_cpu_device::ldb_ex, &m6801_cpu_device::stb_ex, // F &m6801_cpu_device::eorb_ex,&m6801_cpu_device::adcb_ex,&m6801_cpu_device::orb_ex, &m6801_cpu_device::addb_ex,&m6801_cpu_device::ldd_ex, &m6801_cpu_device::std_ex, &m6801_cpu_device::ldx_ex, &m6801_cpu_device::stx_ex }; +void m6801_cpu_device::m6801_io(address_map &map) +{ + map(0x0000, 0x0000).rw(FUNC(m6801_cpu_device::ff_r), FUNC(m6801_cpu_device::p1_ddr_w)); + map(0x0001, 0x0001).rw(FUNC(m6801_cpu_device::ff_r), FUNC(m6801_cpu_device::p2_ddr_w)); + map(0x0002, 0x0002).rw(FUNC(m6801_cpu_device::p1_data_r), FUNC(m6801_cpu_device::p1_data_w)); + map(0x0003, 0x0003).rw(FUNC(m6801_cpu_device::p2_data_r), FUNC(m6801_cpu_device::p2_data_w)); + map(0x0004, 0x0004).rw(FUNC(m6801_cpu_device::ff_r), FUNC(m6801_cpu_device::p3_ddr_w)); // TODO: external in 6801 modes 0–3 & 6 + map(0x0005, 0x0005).rw(FUNC(m6801_cpu_device::ff_r), FUNC(m6801_cpu_device::p4_ddr_w)); // TODO: external in 6801 modes 0–3 + map(0x0006, 0x0006).rw(FUNC(m6801_cpu_device::p3_data_r), FUNC(m6801_cpu_device::p3_data_w)); // TODO: external in 6801 modes 0–3 & 6 + map(0x0007, 0x0007).rw(FUNC(m6801_cpu_device::p4_data_r), FUNC(m6801_cpu_device::p4_data_w)); // TODO: external in 6801 modes 0–3 + map(0x0008, 0x0008).rw(FUNC(m6801_cpu_device::tcsr_r), FUNC(m6801_cpu_device::tcsr_w)); + map(0x0009, 0x0009).rw(FUNC(m6801_cpu_device::ch_r), FUNC(m6801_cpu_device::ch_w)); + map(0x000a, 0x000a).rw(FUNC(m6801_cpu_device::cl_r), FUNC(m6801_cpu_device::cl_w)); + map(0x000b, 0x000b).rw(FUNC(m6801_cpu_device::ocrh_r), FUNC(m6801_cpu_device::ocrh_w)); + map(0x000c, 0x000c).rw(FUNC(m6801_cpu_device::ocrl_r), FUNC(m6801_cpu_device::ocrl_w)); + map(0x000d, 0x000d).r(FUNC(m6801_cpu_device::icrh_r)); + map(0x000e, 0x000e).r(FUNC(m6801_cpu_device::icrl_r)); + map(0x000f, 0x000f).rw(FUNC(m6801_cpu_device::p3_csr_r), FUNC(m6801_cpu_device::p3_csr_w)); // TODO: external in 6801 modes 0–3, 5 & 6 + map(0x0010, 0x0010).rw(FUNC(m6801_cpu_device::sci_rmcr_r), FUNC(m6801_cpu_device::sci_rmcr_w)); + map(0x0011, 0x0011).rw(FUNC(m6801_cpu_device::sci_trcsr_r), FUNC(m6801_cpu_device::sci_trcsr_w)); + map(0x0012, 0x0012).r(FUNC(m6801_cpu_device::sci_rdr_r)); + map(0x0013, 0x0013).w(FUNC(m6801_cpu_device::sci_tdr_w)); + map(0x0014, 0x0014).rw(FUNC(m6801_cpu_device::rcr_r), FUNC(m6801_cpu_device::rcr_w)); +} + void m6801_cpu_device::m6803_mem(address_map &map) { - map(0x0000, 0x001f).rw(FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w)); - map(0x0020, 0x007f).noprw(); /* unused */ - map(0x0080, 0x00ff).ram(); /* 6803 internal RAM */ + m6801_io(map); + map(0x0080, 0x00ff).ram().share(m_internal_ram); +} + +void m6801_cpu_device::m6801_mem(address_map &map) +{ + m6803_mem(map); + map(0xf800, 0xffff).rom().region(DEVICE_SELF, 0); +} + +void m6801u4_cpu_device::m6801u4_io(address_map &map) +{ + m6801_io(map); + map(0x0015, 0x0015).rw(FUNC(m6801u4_cpu_device::ch_r), FUNC(m6801u4_cpu_device::ch_w)); // alternate address + map(0x0016, 0x0016).rw(FUNC(m6801u4_cpu_device::cl_r), FUNC(m6801u4_cpu_device::cl_w)); // " + //map(0x0017, 0x0017).rw(FUNC(m6801u4_cpu_device::tcr1_r), FUNC(m6801u4_cpu_device::tcr1_w)); + map(0x0018, 0x0018).rw(FUNC(m6801u4_cpu_device::tcr2_r), FUNC(m6801u4_cpu_device::tcr2_w)); + map(0x0019, 0x0019).r(FUNC(m6801u4_cpu_device::tsr_r)); + map(0x001a, 0x001a).rw(FUNC(m6801u4_cpu_device::ocr2h_r<1>), FUNC(m6801u4_cpu_device::ocr2h_w<1>)); + map(0x001b, 0x001b).rw(FUNC(m6801u4_cpu_device::ocr2l_r<1>), FUNC(m6801u4_cpu_device::ocr2l_w<1>)); + map(0x001c, 0x001c).rw(FUNC(m6801u4_cpu_device::ocr2h_r<2>), FUNC(m6801u4_cpu_device::ocr2h_w<2>)); + map(0x001d, 0x001d).rw(FUNC(m6801u4_cpu_device::ocr2l_r<2>), FUNC(m6801u4_cpu_device::ocr2l_w<2>)); +} + +void m6801u4_cpu_device::m6801u4_mem(address_map &map) +{ + m6801u4_io(map); + map(0x0040, 0x00ff).ram().share(m_internal_ram); + map(0xf000, 0xffff).rom().region(DEVICE_SELF, 0); +} + +void m6801_cpu_device::hd6801_mem(address_map &map) +{ + m6803_mem(map); + map(0xf000, 0xffff).rom().region(DEVICE_SELF, 0); +} + +void hd6301x_cpu_device::hd6303x_io(address_map &map) +{ + map(0x0001, 0x0001).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::p2_ddr_2bit_w)); + map(0x0003, 0x0003).rw(FUNC(hd6301x_cpu_device::p2_data_r), FUNC(hd6301x_cpu_device::p2_data_w)); + map(0x0008, 0x0008).rw(FUNC(hd6301x_cpu_device::tcsr_r), FUNC(hd6301x_cpu_device::tcsr_w)); + map(0x0009, 0x0009).rw(FUNC(hd6301x_cpu_device::ch_r), FUNC(hd6301x_cpu_device::ch_w)); + map(0x000a, 0x000a).rw(FUNC(hd6301x_cpu_device::cl_r), FUNC(hd6301x_cpu_device::cl_w)); + map(0x000b, 0x000b).rw(FUNC(hd6301x_cpu_device::ocrh_r), FUNC(hd6301x_cpu_device::ocrh_w)); + map(0x000c, 0x000c).rw(FUNC(hd6301x_cpu_device::ocrl_r), FUNC(hd6301x_cpu_device::ocrl_w)); + map(0x000d, 0x000d).r(FUNC(hd6301x_cpu_device::icrh_r)); + map(0x000e, 0x000e).r(FUNC(hd6301x_cpu_device::icrl_r)); + map(0x000f, 0x000f).rw(FUNC(hd6301x_cpu_device::tcsr2_r), FUNC(hd6301x_cpu_device::tcsr2_w)); + map(0x0010, 0x0010).rw(FUNC(hd6301x_cpu_device::sci_rmcr_r), FUNC(hd6301x_cpu_device::sci_rmcr_w)); + map(0x0011, 0x0011).rw(FUNC(hd6301x_cpu_device::sci_trcsr_r), FUNC(hd6301x_cpu_device::sci_trcsr_w)); + map(0x0012, 0x0012).r(FUNC(hd6301x_cpu_device::sci_rdr_r)); + map(0x0013, 0x0013).w(FUNC(hd6301x_cpu_device::sci_tdr_w)); + map(0x0014, 0x0014).rw(FUNC(hd6301x_cpu_device::rcr_r), FUNC(hd6301x_cpu_device::rcr_w)); + map(0x0015, 0x0015).r(FUNC(hd6301x_cpu_device::p5_data_r)); + map(0x0016, 0x0016).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::p6_ddr_w)); + map(0x0017, 0x0017).rw(FUNC(hd6301x_cpu_device::p6_data_r), FUNC(hd6301x_cpu_device::p6_data_w)); + map(0x0019, 0x0019).rw(FUNC(hd6301x_cpu_device::ocr2h_r), FUNC(hd6301x_cpu_device::ocr2h_w)); + map(0x001a, 0x001a).rw(FUNC(hd6301x_cpu_device::ocr2l_r), FUNC(hd6301x_cpu_device::ocr2l_w)); + map(0x001b, 0x001b).rw(FUNC(hd6301x_cpu_device::tcsr3_r), FUNC(hd6301x_cpu_device::tcsr3_w)); + map(0x001c, 0x001c).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::tconr_w)); + map(0x001d, 0x001d).rw(FUNC(hd6301x_cpu_device::t2cnt_r), FUNC(hd6301x_cpu_device::t2cnt_w)); + //map(0x001f, 0x001f).rw(FUNC(hd6301x_cpu_device::tstreg_r), FUNC(hd6301x_cpu_device::tstreg_w)); +} + +void hd6301x_cpu_device::hd6301x_io(address_map &map) +{ + hd6303x_io(map); + map(0x0002, 0x0002).rw(FUNC(hd6301x_cpu_device::p1_data_r), FUNC(hd6301x_cpu_device::p1_data_w)); // external except in single-chip mode + map(0x0004, 0x0004).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::p3_ddr_1bit_w)); // external except in single-chip mode + map(0x0006, 0x0006).rw(FUNC(hd6301x_cpu_device::p3_data_r), FUNC(hd6301x_cpu_device::p3_data_w)); // external except in single-chip mode + map(0x0007, 0x0007).rw(FUNC(hd6301x_cpu_device::p4_data_r), FUNC(hd6301x_cpu_device::p4_data_w)); // external except in single-chip mode + map(0x0018, 0x0018).rw(FUNC(hd6301x_cpu_device::p7_data_r), FUNC(hd6301x_cpu_device::p7_data_w)); // external except in single-chip mode +} + +void hd6301x_cpu_device::hd6303x_mem(address_map &map) +{ + hd6303x_io(map); + map(0x0040, 0x00ff).ram().share(m_internal_ram); +} + +void hd6301x_cpu_device::hd6301x_mem(address_map &map) +{ + hd6301x_io(map); + map(0x0040, 0x00ff).ram().share(m_internal_ram); + map(0xf000, 0xffff).rom().region(DEVICE_SELF, 0); +} + +void hd6301y_cpu_device::hd6303y_io(address_map &map) +{ + hd6303x_io(map); + map(0x0001, 0x0001).w(FUNC(hd6301y_cpu_device::p2_ddr_w)); + map(0x0015, 0x0015).w(FUNC(hd6301y_cpu_device::p5_data_w)); + //map(0x001e, 0x001e).rw(FUNC(hd6301y_cpu_device::sci_trcsr2_r), FUNC(hd6301y_cpu_device::sci_trcsr2_w)); + map(0x0020, 0x0020).rw(FUNC(hd6301y_cpu_device::ff_r), FUNC(hd6301y_cpu_device::p5_ddr_w)); + map(0x0021, 0x0021).rw(FUNC(hd6301y_cpu_device::p6_csr_r), FUNC(hd6301y_cpu_device::p6_csr_w)); + //map(0x0022, 0x0027).noprw(); // reserved } +void hd6301y_cpu_device::hd6301y_io(address_map &map) +{ + hd6303y_io(map); + map(0x0000, 0x0000).rw(FUNC(hd6301y_cpu_device::ff_r), FUNC(hd6301y_cpu_device::p1_ddr_1bit_w)); // external except in single-chip mode + map(0x0002, 0x0002).rw(FUNC(hd6301y_cpu_device::p1_data_r), FUNC(hd6301y_cpu_device::p1_data_w)); // external except in single-chip mode + map(0x0004, 0x0004).rw(FUNC(hd6301y_cpu_device::ff_r), FUNC(hd6301y_cpu_device::p3_ddr_1bit_w)); // external except in single-chip mode + map(0x0005, 0x0005).rw(FUNC(hd6301y_cpu_device::ff_r), FUNC(hd6301y_cpu_device::p4_ddr_w)); // external except in single-chip mode + map(0x0006, 0x0006).rw(FUNC(hd6301y_cpu_device::p3_data_r), FUNC(hd6301y_cpu_device::p3_data_w)); // external except in single-chip mode + map(0x0007, 0x0007).rw(FUNC(hd6301y_cpu_device::p4_data_r), FUNC(hd6301y_cpu_device::p4_data_w)); // external except in single-chip mode + map(0x0018, 0x0018).rw(FUNC(hd6301y_cpu_device::p7_data_r), FUNC(hd6301y_cpu_device::p7_data_w)); // external except in single-chip mode +} -DEFINE_DEVICE_TYPE(M6801, m6801_cpu_device, "m6801", "Motorola M6801") -DEFINE_DEVICE_TYPE(M6803, m6803_cpu_device, "m6803", "Motorola M6803") -DEFINE_DEVICE_TYPE(HD6301, hd6301_cpu_device, "hd6301", "Hitachi HD6301") -DEFINE_DEVICE_TYPE(HD63701, hd63701_cpu_device, "hd63701", "Hitachi HD63701") +void hd6301y_cpu_device::hd6303y_mem(address_map &map) +{ + hd6303y_io(map); + map(0x0040, 0x013f).ram().share(m_internal_ram); +} + +void hd6301y_cpu_device::hd6301y_mem(address_map &map) +{ + hd6301y_io(map); + map(0x0040, 0x013f).ram().share(m_internal_ram); + map(0xc000, 0xffff).rom().region(DEVICE_SELF, 0); +} + + +DEFINE_DEVICE_TYPE(M6801, m6801_cpu_device, "m6801", "Motorola MC6801") +DEFINE_DEVICE_TYPE(M6801U4, m6801u4_cpu_device, "m6801u4", "Motorola MC6801U4") +DEFINE_DEVICE_TYPE(HD6801V0, hd6801v0_cpu_device, "hd6801v0", "Hitachi HD6801V0") +DEFINE_DEVICE_TYPE(M6803, m6803_cpu_device, "m6803", "Motorola MC6803") +DEFINE_DEVICE_TYPE(M6803E, m6803e_cpu_device, "m6803e", "Motorola MC6803E") +DEFINE_DEVICE_TYPE(MC68120, mc68120_device, "mc68120", "Motorola MC68120 IPC") +DEFINE_DEVICE_TYPE(MC68121, mc68121_device, "mc68121", "Motorola MC68121 IPC") +DEFINE_DEVICE_TYPE(HD6301V1, hd6301v1_cpu_device, "hd6301v1", "Hitachi HD6301V1") +DEFINE_DEVICE_TYPE(HD6301X0, hd6301x0_cpu_device, "hd6301x0", "Hitachi HD6301X0") +DEFINE_DEVICE_TYPE(HD6301Y0, hd6301y0_cpu_device, "hd6301y0", "Hitachi HD6301Y0") +DEFINE_DEVICE_TYPE(HD63701V0, hd63701v0_cpu_device, "hd63701v0", "Hitachi HD63701V0") +DEFINE_DEVICE_TYPE(HD63701X0, hd63701x0_cpu_device, "hd63701x0", "Hitachi HD63701X0") +DEFINE_DEVICE_TYPE(HD63701Y0, hd63701y0_cpu_device, "hd63701y0", "Hitachi HD63701Y0") DEFINE_DEVICE_TYPE(HD6303R, hd6303r_cpu_device, "hd6303r", "Hitachi HD6303R") +DEFINE_DEVICE_TYPE(HD6303X, hd6303x_cpu_device, "hd6303x", "Hitachi HD6303X") DEFINE_DEVICE_TYPE(HD6303Y, hd6303y_cpu_device, "hd6303y", "Hitachi HD6303Y") -m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : m6801_cpu_device(mconfig, M6801, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor()) +m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m6801_cpu_device(mconfig, M6801, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(m6803_cpu_device::m6801_mem), this), 64) { } -m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const op_func *insn, const uint8_t *cycles, address_map_constructor internal) +m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const op_func *insn, const u8 *cycles, address_map_constructor internal, int nvram_bytes) : m6800_cpu_device(mconfig, type, tag, owner, clock, insn, cycles, internal) - , m_in_port_func{{*this}, {*this}, {*this}, {*this}} - , m_out_port_func{{*this}, {*this}, {*this}, {*this}} + , device_nvram_interface(mconfig, *this) + , m_in_port_func(*this, 0xff) + , m_out_port_func(*this) , m_out_sc2_func(*this) , m_out_sertx_func(*this) + , m_standby_func(*this) + , m_internal_ram(*this, "internal_ram") + , m_nvram_bytes(nvram_bytes) + , m_nvram_defval(0) + , m_nvram_battery(true) + , m_sclk_divider(8) +{ + std::fill(std::begin(m_port_ddr_override), std::end(m_port_ddr_override), 0); + + // disable nvram by default (set to true if MCU is battery-backed when in standby mode) + nvram_enable_backup(false); +} + +m6801u4_cpu_device::m6801u4_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m6801_cpu_device(mconfig, M6801U4, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(m6801u4_cpu_device::m6801u4_mem), this), 32) +{ +} + +hd6801v0_cpu_device::hd6801v0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m6801_cpu_device(mconfig, HD6801V0, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(hd6801v0_cpu_device::hd6801_mem), this), 64) +{ +} + +m6803_cpu_device::m6803_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m6801_cpu_device(mconfig, M6803, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(m6803_cpu_device::m6803_mem), this), 64) +{ +} + +m6803e_cpu_device::m6803e_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m6801_cpu_device(mconfig, M6803E, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(m6803e_cpu_device::m6803_mem), this), 64) +{ +} + +mc68120_device::mc68120_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal) + : m6801_cpu_device(mconfig, type, tag, owner, clock, m6803_insn, cycles_6803, internal, 0) +{ +} + +mc68120_device::mc68120_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : mc68120_device(mconfig, MC68120, tag, owner, clock, address_map_constructor(FUNC(mc68120_device::m6801_mem), this)) +{ +} + +mc68121_device::mc68121_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : mc68120_device(mconfig, MC68121, tag, owner, clock, address_map_constructor(FUNC(mc68121_device::m6803_mem), this)) +{ +} + +hd6301_cpu_device::hd6301_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const m6800_cpu_device::op_func *insn, const u8 *cycles, address_map_constructor internal, int nvram_bytes) + : m6801_cpu_device(mconfig, type, tag, owner, clock, hd63701_insn, cycles_63701, internal, nvram_bytes) +{ +} + +hd6301v1_cpu_device::hd6301v1_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301_cpu_device(mconfig, HD6301V1, tag, owner, clock, hd63701_insn, cycles_63701, address_map_constructor(FUNC(hd6301v1_cpu_device::hd6801_mem), this), 128) +{ +} + +hd63701v0_cpu_device::hd63701v0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301_cpu_device(mconfig, HD63701V0, tag, owner, clock, hd63701_insn, cycles_63701, address_map_constructor(FUNC(hd63701v0_cpu_device::hd6801_mem), this), 128) +{ +} + +hd6303r_cpu_device::hd6303r_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301_cpu_device(mconfig, HD6303R, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(hd6303r_cpu_device::m6803_mem), this), 128) +{ +} + +hd6301x_cpu_device::hd6301x_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal, int nvram_bytes) + : hd6301_cpu_device(mconfig, type, tag, owner, clock, hd63701_insn, cycles_63701, internal, nvram_bytes) + , m_in_portx_func(*this, 0xff) + , m_out_portx_func(*this) +{ + std::fill(std::begin(m_portx_ddr_override), std::end(m_portx_ddr_override), 0); + + m_sclk_divider = 16; +} + +hd6301x0_cpu_device::hd6301x0_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal, int nvram_bytes) + : hd6301x_cpu_device(mconfig, type, tag, owner, clock, internal, nvram_bytes) +{ +} + +hd6301x0_cpu_device::hd6301x0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301x0_cpu_device(mconfig, HD6301X0, tag, owner, clock, address_map_constructor(FUNC(hd6301x0_cpu_device::hd6301x_mem), this), 192) +{ +} + +hd63701x0_cpu_device::hd63701x0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301x0_cpu_device(mconfig, HD63701X0, tag, owner, clock, address_map_constructor(FUNC(hd63701x0_cpu_device::hd6301x_mem), this), 192) +{ +} + +hd6303x_cpu_device::hd6303x_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301x_cpu_device(mconfig, HD6303X, tag, owner, clock, address_map_constructor(FUNC(hd6303x_cpu_device::hd6303x_mem), this), 192) +{ +} + +hd6301y_cpu_device::hd6301y_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal, int nvram_bytes) + : hd6301x_cpu_device(mconfig, type, tag, owner, clock, internal, nvram_bytes) +{ +} + +hd6301y0_cpu_device::hd6301y0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301y_cpu_device(mconfig, HD6301Y0, tag, owner, clock, address_map_constructor(FUNC(hd6301y0_cpu_device::hd6301y_mem), this), 256) +{ +} + +hd63701y0_cpu_device::hd63701y0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301y_cpu_device(mconfig, HD63701Y0, tag, owner, clock, address_map_constructor(FUNC(hd63701y0_cpu_device::hd6301y_mem), this), 256) +{ +} + +hd6303y_cpu_device::hd6303y_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hd6301y_cpu_device(mconfig, HD6303Y, tag, owner, clock, address_map_constructor(FUNC(hd6303y_cpu_device::hd6303y_mem), this), 256) +{ +} + + +bool m6801_cpu_device::check_irq2_ici() { + return (m_tcsr & (TCSR_EICI|TCSR_ICF)) == (TCSR_EICI|TCSR_ICF); } -m6803_cpu_device::m6803_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : m6801_cpu_device(mconfig, M6803, tag, owner, clock, m6803_insn, cycles_6803, address_map_constructor(FUNC(m6803_cpu_device::m6803_mem), this)) +bool m6801_cpu_device::check_irq2_oci() { + return (m_tcsr & (TCSR_EOCI|TCSR_OCF)) == (TCSR_EOCI|TCSR_OCF); } -hd6301_cpu_device::hd6301_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : hd6301_cpu_device(mconfig, HD6301, tag, owner, clock) +bool m6801_cpu_device::check_irq2_toi() { + return (m_tcsr & (TCSR_ETOI|TCSR_TOF)) == (TCSR_ETOI|TCSR_TOF); } -hd6301_cpu_device::hd6301_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : m6801_cpu_device(mconfig, type, tag, owner, clock, hd63701_insn, cycles_63701) +bool m6801_cpu_device::check_irq2_sci() { + return (((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) == (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) || + ((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) == (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) || + ((m_trcsr & (M6801_TRCSR_TIE|M6801_TRCSR_TDRE)) == (M6801_TRCSR_TIE|M6801_TRCSR_TDRE))); } -hd63701_cpu_device::hd63701_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : m6801_cpu_device(mconfig, HD63701, tag, owner, clock, hd63701_insn, cycles_63701) +void m6801_cpu_device::take_irq2(const char *message, u16 irq_vector) { + m_wai_state &= ~M6800_SLP; + + if (!(m_cc & 0x10)) + enter_interrupt(message, irq_vector); } -hd6303r_cpu_device::hd6303r_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : hd6301_cpu_device(mconfig, HD6303R, tag, owner, clock) +void m6801_cpu_device::check_irq2() { + if (check_irq2_ici()) + { + if (!(m_cc & 0x10)) + standard_irq_callback(M6801_TIN_LINE, m_pc.w.l); + take_irq2("ICI", 0xfff6); + } + else if (check_irq2_oci()) + { + take_irq2("OCI", 0xfff4); + } + else if (check_irq2_toi()) + { + take_irq2("TOI", 0xfff2); + } + else if (check_irq2_sci()) + { + take_irq2("SCI", 0xfff0); + } } -hd6303y_cpu_device::hd6303y_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : hd6301_cpu_device(mconfig, HD6303Y, tag, owner, clock) +void m6801u4_cpu_device::check_irq2() { + if (check_irq2_ici() || (m_tcr[1] & m_tsr & TSR_ICF2)) + { + if (!(m_cc & 0x10)) + standard_irq_callback(M6801_TIN_LINE, m_pc.w.l); + take_irq2("ICI", 0xfff6); + } + else if (check_irq2_oci() || (m_tcr[1] & m_tsr & (TSR_OCF2 | TSR_OCF3))) + { + take_irq2("OCI", 0xfff4); + } + else if (check_irq2_toi()) + { + take_irq2("TOI", 0xfff2); + } + else if (check_irq2_sci()) + { + take_irq2("SCI", 0xfff0); + } } -void m6801_cpu_device::m6800_check_irq2() +void hd6301x_cpu_device::check_irq2() { - if ((m_tcsr & (TCSR_EICI|TCSR_ICF)) == (TCSR_EICI|TCSR_ICF)) + if (check_irq2_ici()) + { + if (!(m_cc & 0x10)) + standard_irq_callback(M6801_TIN_LINE, m_pc.w.l); + take_irq2("ICI", 0xfff6); + } + else if (check_irq2_oci() || (m_tcsr2 & (TCSR2_EOCI2|TCSR2_OCF2)) == (TCSR2_EOCI2|TCSR2_OCF2)) + { + take_irq2("OCI", 0xfff4); + } + else if (check_irq2_toi()) { - TAKE_ICI; - standard_irq_callback(M6801_TIN_LINE); + take_irq2("TOI", 0xfff2); } - else if ((m_tcsr & (TCSR_EOCI|TCSR_OCF)) == (TCSR_EOCI|TCSR_OCF)) + else if ((m_tcsr3 & 0xc0) == 0xc0) { - TAKE_OCI; + take_irq2("CMI", 0xffec); } - else if ((m_tcsr & (TCSR_ETOI|TCSR_TOF)) == (TCSR_ETOI|TCSR_TOF)) + else if (m_irq_state[HD6301_IRQ2_LINE] != CLEAR_LINE && m_ram_ctrl & 2) { - TAKE_TOI; + if (!(m_cc & 0x10)) + standard_irq_callback(HD6301_IRQ2_LINE, m_pc.w.l); + take_irq2("IRQ2", 0xffea); } - else if (((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) == (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) || - ((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) == (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) || - ((m_trcsr & (M6801_TRCSR_TIE|M6801_TRCSR_TDRE)) == (M6801_TRCSR_TIE|M6801_TRCSR_TDRE))) + else if (check_irq2_sci()) { - LOG("SCI interrupt\n"); - TAKE_SCI; + take_irq2("SCI", 0xfff0); } } +void hd6301y_cpu_device::check_irq2() +{ + if ((m_p6csr & 0xc0) == 0xc0) + { + if (!(m_cc & 0x10)) + standard_irq_callback(M6801_IS3_LINE, m_pc.w.l); + take_irq2("ISI", 0xfff8); + } + else + hd6301x_cpu_device::check_irq2(); +} + +bool hd6301x_cpu_device::check_irq1_enabled() +{ + return hd6301_cpu_device::check_irq1_enabled() && (m_ram_ctrl & 1); +} + + +void m6801_cpu_device::set_timer_event() +{ + m_timer_next = (OCD < TOD) ? OCD : TOD; +} + +void m6801u4_cpu_device::set_timer_event() +{ + m6801_cpu_device::set_timer_event(); + + if (OC2D < m_timer_next) + m_timer_next = OC2D; + if (OC3D < m_timer_next) + m_timer_next = OC3D; +} + +void hd6301x_cpu_device::set_timer_event() +{ + m6801_cpu_device::set_timer_event(); + + if (OC2D < m_timer_next) + m_timer_next = OC2D; +} + +/* when change freerunningcounter or outputcapture */ +void m6801_cpu_device::modified_counters() +{ + OCH = (OC >= CT) ? CTH : CTH+1; + set_timer_event(); +} + +void m6801u4_cpu_device::modified_counters() +{ + OCH = (OC >= CT) ? CTH : CTH+1; + OC2H = (OC2 >= CT) ? CTH : CTH+1; + OC3H = (OC3 >= CT) ? CTH : CTH+1; + set_timer_event(); +} + +void hd6301x_cpu_device::modified_counters() +{ + OCH = (OC >= CT) ? CTH : CTH+1; + OC2H = (OC2 >= CT) ? CTH : CTH+1; + set_timer_event(); +} + /* check OCI or TOI */ void m6801_cpu_device::check_timer_event() { - /* OCI */ + // OCI if (CTD >= OCD) { - OCH++; // next IRQ point + OCH++; // next IRQ point m_tcsr |= TCSR_OCF; m_pending_tcsr |= TCSR_OCF; - MODIFIED_tcsr; - if((m_tcsr & TCSR_EOCI) && m_wai_state & M6800_SLP) - m_wai_state &= ~M6800_SLP; - if ( !(m_cc & 0x10) && (m_tcsr & TCSR_EOCI)) - TAKE_OCI; // if output on P21 is enabled, let's do it if (m_port_ddr[1] & 2) { m_port_data[1] &= ~2; m_port_data[1] |= (m_tcsr & TCSR_OLVL) << 1; - m_port2_written = 1; + m_port2_written = true; write_port2(); } } - /* TOI */ + + // TOI if (CTD >= TOD) { - TOH++; // next IRQ point + TOH++; // next IRQ point #if 0 - CLEANUP_COUNTERS(); + cleanup_counters(); #endif m_tcsr |= TCSR_TOF; m_pending_tcsr |= TCSR_TOF; - MODIFIED_tcsr; - if((m_tcsr & TCSR_ETOI) && m_wai_state & M6800_SLP) - m_wai_state &= ~M6800_SLP; - if ( !(m_cc & 0x10) && (m_tcsr & TCSR_ETOI)) - TAKE_TOI; } - /* set next event */ - SET_TIMER_EVENT; + + check_irq2(); + + // set next event + set_timer_event(); +} + +void m6801u4_cpu_device::check_timer_event() +{ + // OCI + if (CTD >= OCD) + { + OCH++; // next IRQ point + m_tcsr |= TCSR_OCF; + m_pending_tcsr |= TCSR_OCF; + + // TODO: output to P21 + } + if (CTD >= OC2D) + { + OC2H++; // next IRQ point + m_tsr |= TSR_OCF2; + m_pending_tsr |= TSR_OCF2; + + // TODO: output to P11 + } + if (CTD >= OC3D) + { + OC3H++; // next IRQ point + m_tsr |= TSR_OCF3; + m_pending_tsr |= TSR_OCF3; + + // TODO: output to P12 + } + + // TOI + if (CTD >= TOD) + { + TOH++; // next IRQ point +#if 0 + cleanup_counters(); +#endif + m_tcsr |= TCSR_TOF; + m_pending_tcsr |= TCSR_TOF; + } + + check_irq2(); + + // set next event + set_timer_event(); +} + +void hd6301x_cpu_device::check_timer_event() +{ + // OCI + if (CTD >= OCD) + { + OCH++; // next IRQ point + m_tcsr |= TCSR_OCF; + m_pending_tcsr |= TCSR_OCF; + + // if output on P21 is enabled, let's do it + if (m_tcsr2 & TCSR2_OE1) + { + m_port_data[1] &= ~2; + m_port_data[1] |= (m_tcsr & TCSR_OLVL) << 1; + m_port2_written = true; + write_port2(); + } + } + if (CTD >= OC2D) + { + OC2H++; // next IRQ point + m_tcsr2 |= TCSR2_OCF2; + m_pending_tcsr2 |= TCSR2_OCF2; + + // if output on P25 is enabled, let's do it + if (m_tcsr2 & TCSR2_OE2) + { + if (m_tcsr2 & TCSR2_OLVL2) + m_port_data[1] |= 0x20; + else + m_port_data[1] &= ~0x20; + m_port2_written = true; + write_port2(); + } + } + + // TOI + if (CTD >= TOD) + { + TOH++; // next IRQ point +#if 0 + cleanup_counters(); +#endif + m_tcsr |= TCSR_TOF; + m_pending_tcsr |= TCSR_TOF; + } + + check_irq2(); + + // set next event + set_timer_event(); } void m6801_cpu_device::increment_counter(int amount) @@ -388,23 +863,83 @@ void m6801_cpu_device::increment_counter(int amount) check_timer_event(); } -void m6801_cpu_device::EAT_CYCLES() +void hd6301x_cpu_device::increment_counter(int amount) +{ + m6800_cpu_device::increment_counter(amount); + if (m_t2cnt_written) + m_t2cnt_written = false; + else if (BIT(m_tcsr3, 4)) + { + switch (m_tcsr3 & 0x03) + { + case 0x00: + // Timer 2 input = E clock + increment_t2cnt(amount); + break; + + case 0x01: + // Timer 2 input = E clock/8 + increment_t2cnt((amount + (CTD & 0x0007)) >> 3); + break; + + case 0x02: + // Timer 2 input = E clock/128 + increment_t2cnt((amount + (CTD & 0x007f)) >> 7); + break; + + case 0x03: + // Timer 2 input = external Tclk + break; + } + } + CTD += amount; + if (CTD >= m_timer_next || (m_tcsr3 & 0xc0) == 0xc0) + check_timer_event(); +} + +void m6801_cpu_device::eat_cycles() { int cycles_to_eat = std::min(int(m_timer_next - CTD), m_icount); if (cycles_to_eat > 0) increment_counter(cycles_to_eat); } +void hd6301x_cpu_device::eat_cycles() +{ + if (BIT(m_tcsr3, 4)) + { + while (m_icount > 0 && m_wai_state & (M6800_WAI | M6800_SLP)) + increment_counter(1); + } + else + m6801_cpu_device::eat_cycles(); +} + /* cleanup high-word of counters */ -void m6801_cpu_device::CLEANUP_COUNTERS() +void m6801_cpu_device::cleanup_counters() { OCH -= CTH; TOH -= CTH; CTH = 0; - SET_TIMER_EVENT; + set_timer_event(); + if (CTD >= m_timer_next) + check_timer_event(); +} + +void m6801u4_cpu_device::cleanup_counters() +{ + OC2H -= CTH; + OC3H -= CTH; + m6801_cpu_device::cleanup_counters(); +} + +void hd6301x_cpu_device::cleanup_counters() +{ + OC2H -= CTH; + m6801_cpu_device::cleanup_counters(); } -void m6801_cpu_device::set_rmcr(uint8_t data) +void m6801_cpu_device::set_rmcr(u8 data) { if (m_rmcr == data) return; @@ -413,13 +948,15 @@ void m6801_cpu_device::set_rmcr(uint8_t data) switch ((m_rmcr & M6801_RMCR_CC_MASK) >> 2) { case 0: - m_sci_timer->enable(false); + LOGSER("SCI: Using external serial clock: false\n"); + reset_sci_timer(); m_use_ext_serclock = false; break; case 3: // external clock + LOGSER("SCI: Using external serial clock: true\n"); + reset_sci_timer(); m_use_ext_serclock = true; - m_sci_timer->enable(false); break; case 1: @@ -427,7 +964,7 @@ void m6801_cpu_device::set_rmcr(uint8_t data) { int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; attotime period = cycles_to_attotime(divisor); - + LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, period.as_hz()); m_sci_timer->adjust(period, 0, period); m_use_ext_serclock = false; } @@ -435,17 +972,57 @@ void m6801_cpu_device::set_rmcr(uint8_t data) } } -int m6801_cpu_device::m6800_rx() +void hd6301x_cpu_device::set_rmcr(u8 data) +{ + if (m_rmcr == data) return; + + m_rmcr = data; + + switch ((m_rmcr & 0x1c) >> 2) + { + case 0: // TODO: clock sync + case 3: + case 7: // external clock + LOGSER("SCI: Using external serial clock: true\n"); + reset_sci_timer(); + m_use_ext_serclock = true; + break; + + case 1: + case 2: + case 4: // TODO: clock sync + case 5: + case 6: + if (BIT(m_rmcr, 5)) + { + LOGSER("SCI: Using Timer 2 clock\n"); + reset_sci_timer(); + } + else + { + int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; + attotime period = cycles_to_attotime(divisor); + LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, period.as_hz()); + m_sci_timer->adjust(period, 0, period); + } + m_use_ext_serclock = false; + break; + } +} + +int m6801_cpu_device::m6801_rx() { return (m_in_port_func[1]() & M6801_PORT2_IO3) >> 3; } void m6801_cpu_device::serial_transmit() { - LOGTXTICK("Tx Tick\n"); + LOGTXTICK("SCI Tx Tick presenting: %d\n", m_tx); if (m_trcsr & M6801_TRCSR_TE) { + int old_m_tx = m_tx; // Detect line change + // force Port 2 bit 4 as output m_port_ddr[1] |= M6801_PORT2_IO4; @@ -476,7 +1053,7 @@ void m6801_cpu_device::serial_transmit() // transmit buffer is full, send data // load TDR to shift register - m_tsr = m_tdr; + m_tshr = m_tdr; // transmit buffer is empty, set TDRE flag m_trcsr |= M6801_TRCSR_TDRE; @@ -486,7 +1063,7 @@ void m6801_cpu_device::serial_transmit() m_txbits++; - LOGTX("Transmit START Data %02x\n", m_tsr); + LOGTX("SCI Transmit START Data %02x\n", m_tshr); } break; @@ -494,21 +1071,21 @@ void m6801_cpu_device::serial_transmit() // send stop bit '1' m_tx = 1; - CHECK_IRQ_LINES(); + check_irq_lines(); m_txbits = M6801_SERIAL_START; - LOGTX("Transmit STOP\n"); + LOGTX("SCI Transmit STOP\n"); break; default: // send data bit '0' or '1' - m_tx = m_tsr & 0x01; + m_tx = m_tshr & 0x01; // shift transmit register - m_tsr >>= 1; + m_tshr >>= 1; - LOGTX("Transmit Bit %u: %u\n", m_txbits, m_tx); + LOGTX("SCI Tx Present Bit %u: %u\n", m_txbits, m_tx); m_txbits++; break; @@ -516,30 +1093,33 @@ void m6801_cpu_device::serial_transmit() break; } - m_out_sertx_func((m_tx == 1) ? ASSERT_LINE : CLEAR_LINE); - m_port2_written = 1; + if (old_m_tx != m_tx) // call callback only if line has changed + { + m_out_sertx_func((m_tx == 1) ? ASSERT_LINE : CLEAR_LINE); + } + m_port2_written = true; write_port2(); } } void m6801_cpu_device::serial_receive() { - LOGRXTICK("Rx Tick TRCSR %02x bits %u check %02x\n", m_trcsr, m_rxbits, m_trcsr & M6801_TRCSR_RE); + LOGRXTICK("SCI Rx Tick TRCSR %02x bits %u check %02x\n", m_trcsr, m_rxbits, m_trcsr & M6801_TRCSR_RE); if (m_trcsr & M6801_TRCSR_RE) { if (m_trcsr & M6801_TRCSR_WU) { // wait for 10 bits of '1' - if (m6800_rx() == 1) + if (m6801_rx() == 1) { m_rxbits++; - LOGRX("Received WAKE UP bit %u\n", m_rxbits); + LOGRX("SCI Received WAKE UP bit %u\n", m_rxbits); if (m_rxbits == 10) { - LOGRX("Receiver Wake Up\n"); + LOGRX("SCI Receiver Wake Up\n"); m_trcsr &= ~M6801_TRCSR_WU; m_rxbits = M6801_SERIAL_START; @@ -547,7 +1127,7 @@ void m6801_cpu_device::serial_receive() } else { - LOGRX("Receiver Wake Up interrupted\n"); + LOGRX("SCI Receiver Wake Up interrupted\n"); m_rxbits = M6801_SERIAL_START; } @@ -558,28 +1138,28 @@ void m6801_cpu_device::serial_receive() switch (m_rxbits) { case M6801_SERIAL_START: - if (m6800_rx() == 0) + if (m6801_rx() == 0) { // start bit found m_rxbits++; - LOGRX("Received START bit\n"); + LOGRX("SCI Received START bit\n"); } break; case M6801_SERIAL_STOP: - if (m6800_rx() == 1) + if (m6801_rx() == 1) { - LOGRX("Received STOP bit\n"); + LOGRX("SCI Received STOP bit\n"); if (m_trcsr & M6801_TRCSR_RDRF) { // overrun error m_trcsr |= M6801_TRCSR_ORFE; - LOGRX("Receive Overrun Error\n"); + LOGRX("SCI Receive Overrun Error\n"); - CHECK_IRQ_LINES(); + check_irq_lines(); } else { @@ -588,12 +1168,12 @@ void m6801_cpu_device::serial_receive() // transfer data into receive register m_rdr = m_rsr; - LOGRX("Receive Data Register: %02x\n", m_rdr); + LOGRX("SCI Receive Data Register: %02x\n", m_rdr); // set RDRF flag m_trcsr |= M6801_TRCSR_RDRF; - CHECK_IRQ_LINES(); + check_irq_lines(); } } } @@ -609,9 +1189,9 @@ void m6801_cpu_device::serial_receive() m_trcsr |= M6801_TRCSR_ORFE; m_trcsr &= ~M6801_TRCSR_RDRF; - LOGRX("Receive Framing Error\n"); + LOGRX("SCI Receive Framing Error\n"); - CHECK_IRQ_LINES(); + check_irq_lines(); } m_rxbits = M6801_SERIAL_START; @@ -622,9 +1202,9 @@ void m6801_cpu_device::serial_receive() m_rsr >>= 1; // receive bit into register - m_rsr |= (m6800_rx() << 7); + m_rsr |= (m6801_rx() << 7); - LOGRX("Received DATA bit %u: %u\n", m_rxbits, BIT(m_rsr, 7)); + LOGRX("SCI RX sampled DATA bit %u: %u\n", m_rxbits, BIT(m_rsr, 7)); m_rxbits++; break; @@ -633,24 +1213,59 @@ void m6801_cpu_device::serial_receive() } } -TIMER_CALLBACK_MEMBER( m6801_cpu_device::sci_tick ) +TIMER_CALLBACK_MEMBER(m6801_cpu_device::sci_tick) { serial_transmit(); serial_receive(); } +void m6801_cpu_device::sci_clock_internal(u8 divider) +{ + m_sci_clocks++; + + if (m_sci_clocks >= divider) + { + m_sci_clocks = 0; + sci_tick(0); + } +} + +void m6801_cpu_device::clock_serial() +{ + if (m_use_ext_serclock) + sci_clock_internal(m_sclk_divider); +} + +void m6801_cpu_device::reset_sci_timer() +{ + m_sci_clocks = 0; + m_sci_timer->adjust(attotime::never); +} + void m6801_cpu_device::execute_set_input(int irqline, int state) { switch (irqline) { - case M6801_SC1_LINE: - if (!m_sc1_state && (CLEAR_LINE != state)) + case M6801_STBY_LINE: + if (!standby() && state != CLEAR_LINE) + { + // clock stops, MCU goes into reset state, all pins except XTAL and STBY go high impedance + suspend(SUSPEND_REASON_CLOCK, true); + m_standby_func(1); + + // once in standby, it can only recover from it after a reset + } + break; + + case M6801_IS3_LINE: + if (!m_is3_state && state != CLEAR_LINE) { if (!m_port3_latched && (m_p3csr & M6801_P3CSR_LE)) { // latch input data to port 3 - m_port_data[2] = (m_in_port_func[2]() & (m_port_ddr[2] ^ 0xff)) | (m_port_data[2] & m_port_ddr[2]); + u8 ddr = m_port_ddr[2] & ~m_port_ddr_override[2]; + m_port_data[2] = (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr); m_port3_latched = 1; LOGPORT("Latched Port 3 Data: %02x\n", m_port_data[2]); @@ -662,23 +1277,20 @@ void m6801_cpu_device::execute_set_input(int irqline, int state) LOGPORT("Not latching Port 3 Data:%s%s", m_port3_latched ? " already latched" : "", (m_p3csr & M6801_P3CSR_LE) ? "" : " LE clear"); } } - m_sc1_state = ASSERT_LINE == state; - if (CLEAR_LINE != state) - standard_irq_callback(M6801_SC1_LINE); // re-entrant - do it after setting m_sc1_state + m_is3_state = state; break; case M6801_TIN_LINE: if (state != m_irq_state[M6801_TIN_LINE]) { m_irq_state[M6801_TIN_LINE] = state; - //edge = (state == CLEAR_LINE ) ? 2 : 0; - if( ((m_tcsr&TCSR_IEDG) ^ (state==CLEAR_LINE ? TCSR_IEDG : 0))==0 ) + //edge = (state == CLEAR_LINE) ? 2 : 0; + if (((m_tcsr & TCSR_IEDG) ^ (state == CLEAR_LINE ? TCSR_IEDG : 0)) == 0) return; /* active edge in */ m_tcsr |= TCSR_ICF; m_pending_tcsr |= TCSR_ICF; m_input_capture = CT; - MODIFIED_tcsr; } break; @@ -688,44 +1300,82 @@ void m6801_cpu_device::execute_set_input(int irqline, int state) } } - -void m6801_cpu_device::device_resolve_objects() +void hd6301y_cpu_device::execute_set_input(int irqline, int state) { - for (auto &cb : m_in_port_func) - cb.resolve_safe(0xff); - for (auto &cb : m_out_port_func) - cb.resolve_safe(); - m_out_sc2_func.resolve_safe(); - m_out_sertx_func.resolve_safe(); + switch (irqline) + { + case M6801_IS3_LINE: + // interrupt at falling edge + if (!state && m_irq_state[M6801_IS3_LINE]) + { + m_p6csr |= 0x80; // IS flag + m_pending_isf_clear = false; + } + + m_irq_state[M6801_IS3_LINE] = state; + break; + + default: + m6801_cpu_device::execute_set_input(irqline, state); + break; + } } + void m6801_cpu_device::device_start() { m6800_cpu_device::device_start(); - m_sci_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m6801_cpu_device::sci_tick),this)); + m_sci_timer = timer_alloc(FUNC(m6801_cpu_device::sci_tick), this); - m_port_ddr[3] = 0; - m_port_data[3] = 0; + std::fill(std::begin(m_port_ddr), std::end(m_port_ddr), 0); + std::fill(std::begin(m_port_data), std::end(m_port_data), 0); + m_p3csr = 0; + m_tcsr = 0; + m_pending_tcsr = 0; + m_ram_ctrl = 0; + m_counter.d = 0; + m_output_compare[0].d = 0; m_input_capture = 0; + m_pending_isf_clear = false; + m_port3_latched = 0; + m_port2_written = false; + + m_trcsr = 0; + m_rmcr = 0; m_rdr = 0; m_tdr = 0; - m_rmcr = 0; - m_ram_ctrl = 0; + m_rsr = 0; + m_tshr = 0; + m_rxbits = 0; + m_txbits = 0; + m_txstate = 0; + m_trcsr_read_tdre = 0; + m_trcsr_read_orfe = 0; + m_trcsr_read_rdrf = 0; + m_tx = 0; + m_sci_clocks = 0; + m_use_ext_serclock = false; + + m_latch09 = 0; + m_is3_state = 0; + m_timer_over.d = 0; + m_timer_next = 0; + save_item(NAME(m_nvram_battery)); save_item(NAME(m_port_ddr)); save_item(NAME(m_port_data)); + save_item(NAME(m_port_ddr_override)); save_item(NAME(m_p3csr)); save_item(NAME(m_tcsr)); save_item(NAME(m_pending_tcsr)); - save_item(NAME(m_irq2)); save_item(NAME(m_ram_ctrl)); save_item(NAME(m_counter.d)); - save_item(NAME(m_output_compare.d)); + save_item(NAME(m_output_compare[0].d)); save_item(NAME(m_input_capture)); - save_item(NAME(m_p3csr_is3_flag_read)); + save_item(NAME(m_pending_isf_clear)); save_item(NAME(m_port3_latched)); save_item(NAME(m_port2_written)); @@ -734,7 +1384,7 @@ void m6801_cpu_device::device_start() save_item(NAME(m_rdr)); save_item(NAME(m_tdr)); save_item(NAME(m_rsr)); - save_item(NAME(m_tsr)); + save_item(NAME(m_tshr)); save_item(NAME(m_rxbits)); save_item(NAME(m_txbits)); save_item(NAME(m_txstate)); @@ -742,37 +1392,86 @@ void m6801_cpu_device::device_start() save_item(NAME(m_trcsr_read_orfe)); save_item(NAME(m_trcsr_read_rdrf)); save_item(NAME(m_tx)); - save_item(NAME(m_ext_serclock)); + save_item(NAME(m_sci_clocks)); save_item(NAME(m_use_ext_serclock)); save_item(NAME(m_latch09)); - + save_item(NAME(m_is3_state)); save_item(NAME(m_timer_over.d)); - save_item(NAME(m_timer_next)); +} + +void m6801u4_cpu_device::device_start() +{ + m6801_cpu_device::device_start(); + + m_tcr[0] = 0; + m_tcr[1] = 0; + m_tsr = 0; + m_pending_tsr = 0; + m_output_compare[1].d = 0; + m_output_compare[2].d = 0; + + save_item(NAME(m_tcr)); + save_item(NAME(m_tsr)); + save_item(NAME(m_pending_tsr)); + save_item(NAME(m_output_compare[1].d)); + save_item(NAME(m_output_compare[2].d)); +} + +void hd6301x_cpu_device::device_start() +{ + m6801_cpu_device::device_start(); + + std::fill(std::begin(m_portx_ddr), std::end(m_portx_ddr), 0); + std::fill(std::begin(m_portx_data), std::end(m_portx_data), 0); + m_tcsr2 = 0; + m_pending_tcsr2 = 0; + m_output_compare[1].d = 0; + + m_t2cnt = 0; + m_tconr = 0; + m_tcsr3 = 0; + m_tout3 = false; + m_t2cnt_written = false; + + save_item(NAME(m_portx_ddr)); + save_item(NAME(m_portx_data)); + save_item(NAME(m_portx_ddr_override)); + save_item(NAME(m_tcsr2)); + save_item(NAME(m_pending_tcsr2)); + save_item(NAME(m_output_compare[1].d)); + + save_item(NAME(m_t2cnt)); + save_item(NAME(m_tconr)); + save_item(NAME(m_tcsr3)); + save_item(NAME(m_tout3)); + save_item(NAME(m_t2cnt_written)); +} + +void hd6301y_cpu_device::device_start() +{ + hd6301x_cpu_device::device_start(); - save_item(NAME(m_sc1_state)); + m_p6csr = 0; + save_item(NAME(m_p6csr)); } void m6801_cpu_device::device_reset() { m6800_cpu_device::device_reset(); - m_irq_state[M6801_TIN_LINE] = 0; - m_sc1_state = 0; + m_standby_func(0); + m_is3_state = 0; - m_port_ddr[0] = 0x00; - m_port_ddr[1] = 0x00; - m_port_ddr[2] = 0x00; - m_port_data[0] = 0; + std::fill(std::begin(m_port_ddr), std::end(m_port_ddr), 0); m_p3csr = 0x00; - m_p3csr_is3_flag_read = 0; - m_port2_written = 0; + m_pending_isf_clear = false; + m_port2_written = false; m_port3_latched = 0; /* TODO: on reset port 2 should be read to determine the operating mode (bits 0-2) */ m_tcsr = 0x00; m_pending_tcsr = 0x00; - m_irq2 = 0; CTD = 0x0000; OCD = 0xffff; TOD = 0xffff; @@ -788,19 +1487,266 @@ void m6801_cpu_device::device_reset() m_trcsr_read_tdre = 0; m_trcsr_read_orfe = 0; m_trcsr_read_rdrf = 0; - m_ext_serclock = 0; m_use_ext_serclock = false; set_rmcr(0); } +void m6801u4_cpu_device::device_reset() +{ + m6801_cpu_device::device_reset(); + + m_tcr[0] = 0; + m_tcr[1] = 0; + m_tsr = 0; + m_pending_tsr = 0; +} + +void hd6301x_cpu_device::device_reset() +{ + m6801_cpu_device::device_reset(); + + std::fill(std::begin(m_portx_ddr), std::end(m_portx_ddr), 0); + + m_tcsr2 = 0x00; + m_pending_tcsr2 = 0x00; + OC2D = 0xffff; + m_ram_ctrl = (m_ram_ctrl & 0x80) | 0x7c; + + m_t2cnt = 0x00; + m_tconr = 0xff; + m_tcsr3 = 0x00; + m_tout3 = false; + m_t2cnt_written = false; + + m_p3csr = 0; // does not have this reg +} + +void hd6301x0_cpu_device::device_reset() +{ + hd6301x_cpu_device::device_reset(); + + // port 4 is write-only on X0 + m_port_ddr[3] = 0xff; +} + +void hd6301y_cpu_device::device_reset() +{ + hd6301x_cpu_device::device_reset(); + + m_ram_ctrl = (m_ram_ctrl & 0x80) | 0x78; + m_p6csr = 7; +} + +u8 mc68120_device::dpram_r(offs_t offset) +{ + return m_internal_ram[offset & 0x7f]; +} + +void mc68120_device::dpram_w(offs_t offset, u8 data) +{ + m_internal_ram[offset & 0x7f] = data; +} + + +// nvram handling + +bool m6801_cpu_device::nvram_write(util::write_stream &file) +{ + // if it's currently not battery-backed, don't save at all + if (!m_nvram_battery) + return true; + + std::error_condition err; + size_t actual; + + std::tie(err, actual) = write(file, &m_internal_ram[0], m_nvram_bytes); + if (err) + return false; + + // upper bits of RAM control register + u8 ram_ctrl = m_ram_ctrl & 0xc0; + std::tie(err, actual) = write(file, &ram_ctrl, 1); + if (err) + return false; + + return true; +} + +bool m6801_cpu_device::nvram_read(util::read_stream &file) +{ + std::error_condition err; + size_t actual; + + std::tie(err, actual) = read(file, &m_internal_ram[0], m_nvram_bytes); + if (err || (m_nvram_bytes != actual)) + return false; + + // upper bits of RAM control register + u8 ram_ctrl = 0; + std::tie(err, actual) = read(file, &ram_ctrl, 1); + if (err || (1 != actual)) + return false; + m_ram_ctrl |= ram_ctrl & 0xc0; + + return true; +} + +void m6801_cpu_device::nvram_default() +{ + if (!nvram_backup_enabled() || m_nvram_bytes == 0) + return; + + // default nvram from mytag:nvram region if it exists + memory_region *region = memregion("nvram"); + if (region != nullptr) + { + if (region->bytes() != m_nvram_bytes) + fatalerror("%s: Wrong region size (expected 0x%x, found 0x%x)", region->name(), m_nvram_bytes, region->bytes()); + + std::copy_n(®ion->as_u8(), m_nvram_bytes, &m_internal_ram[0]); + m_ram_ctrl |= 0x80; + } + else + { + std::fill_n(&m_internal_ram[0], m_nvram_bytes, m_nvram_defval); + m_ram_ctrl &= 0x3f; + } +} + +// HD6301* doesn't have a separate VCC Standby pin, so more internal registers are kept intact while in standby + +bool hd6301_cpu_device::nvram_write(util::write_stream &file) +{ + // if it's currently not battery-backed, don't save at all + if (!m_nvram_battery) + return true; + + if (!m6801_cpu_device::nvram_write(file)) + return false; + + std::vector<u8> buf(7); + + // misc registers + buf[0] = m_s.b.h; + buf[1] = m_s.b.l; + buf[2] = m_x.b.h; + buf[3] = m_x.b.l; + buf[4] = m_d.b.h; + buf[5] = m_d.b.l; + buf[6] = m_tdr; + + // port output latches + buf.insert(buf.end(), m_port_data, m_port_data + sizeof(m_port_data)); + + auto const [err, actual] = write(file, buf.data(), buf.size()); + return !err; +} + +bool hd6301x_cpu_device::nvram_write(util::write_stream &file) +{ + // if it's currently not battery-backed, don't save at all + if (!m_nvram_battery) + return true; + + if (!hd6301_cpu_device::nvram_write(file)) + return false; + + std::vector<u8> buf; + + // port output latches + buf.insert(buf.begin(), m_portx_data, m_portx_data + sizeof(m_portx_data)); + + auto const [err, actual] = write(file, buf.data(), buf.size()); + return !err; +} + +bool hd6301_cpu_device::nvram_read(util::read_stream &file) +{ + if (!m6801_cpu_device::nvram_read(file)) + return false; + + std::error_condition err; + size_t actual; + u8 buf[7]; + + // misc registers + std::tie(err, actual) = read(file, &buf, sizeof(buf)); + if (err || (sizeof(buf) != actual)) + return false; + + m_s.b.h = buf[0]; + m_s.b.l = buf[1]; + m_x.b.h = buf[2]; + m_x.b.l = buf[3]; + m_d.b.h = buf[4]; + m_d.b.l = buf[5]; + m_tdr = buf[6]; + + // port output latches + std::tie(err, actual) = read(file, &m_port_data[0], sizeof(m_port_data)); + if (err || (sizeof(m_port_data) != actual)) + return false; + + return true; +} + +bool hd6301x_cpu_device::nvram_read(util::read_stream &file) +{ + if (!hd6301_cpu_device::nvram_read(file)) + return false; + + // port output latches + auto const [err, actual] = read(file, &m_portx_data[0], sizeof(m_portx_data)); + return !err && (sizeof(m_portx_data) == actual); +} + + + +// internal registers + +void m6801_cpu_device::p1_ddr_w(u8 data) +{ + LOGPORT("Port 1 Data Direction Register: %02x\n", data); + + if (m_port_ddr[0] != data) + { + m_port_ddr[0] = data; + m_out_port_func[0](0, (m_port_data[0] & m_port_ddr[0]) | (m_port_ddr[0] ^ 0xff), m_port_ddr[0]); + } +} + +void hd6301y_cpu_device::p1_ddr_1bit_w(u8 data) +{ + // HD6301Y DDR1 is 1-bit (HD6301X does not have DDR1) + hd6301_cpu_device::p1_ddr_w(BIT(data, 0) ? 0xff : 0x00); +} + +u8 m6801_cpu_device::p1_data_r() +{ + u8 ddr = m_port_ddr[0] & ~m_port_ddr_override[0]; + + if (ddr == 0xff) + return m_port_data[0]; + else + return (m_in_port_func[0]() & ~ddr) | (m_port_data[0] & ddr); +} + +void m6801_cpu_device::p1_data_w(u8 data) +{ + LOGPORT("Port 1 Data Register: %02x\n", data); + + m_port_data[0] = data; + m_out_port_func[0](0, (m_port_data[0] & m_port_ddr[0]) | (m_port_ddr[0] ^ 0xff), m_port_ddr[0]); +} + void m6801_cpu_device::write_port2() { if (!m_port2_written) return; - uint8_t data = m_port_data[1]; - uint8_t ddr = m_port_ddr[1] & 0x1f; + u8 data = m_port_data[1]; + u8 ddr = m_port_ddr[1] & 0x1f; if ((ddr != 0x1f) && ddr) { @@ -810,461 +1756,822 @@ void m6801_cpu_device::write_port2() if (m_trcsr & M6801_TRCSR_TE) { data = (data & 0xef) | (m_tx << 4); + ddr |= 0x10; } data &= 0x1f; - m_out_port_func[1](data); + m_out_port_func[1](0, data, ddr); } -/* - if change_pc() direccted these areas ,Call hd63701_trap_pc(). - 'mode' is selected by the sense of p2.0,p2.1,and p2.3 at reset timming. - mode 0,1,2,4,6 : $0000-$001f - mode 5 : $0000-$001f,$0200-$efff - mode 7 : $0000-$001f,$0100-$efff -*/ - -void m6801_cpu_device::set_os3(int state) +void hd6301x_cpu_device::write_port2() { - LOG("OS3: %u\n", state); + if (!m_port2_written) return; - m_out_sc2_func(state); -} + u8 ddr = m_port_ddr[1]; + if (m_tcsr2 & TCSR2_OE1) + ddr |= 0x02; + if (m_tcsr2 & TCSR2_OE2) + ddr |= 0x20; -READ8_MEMBER( m6801_cpu_device::m6801_io_r ) -{ - uint8_t data = 0; + u8 data = (m_port_data[1] & ddr) | (ddr ^ 0xff); - switch (offset) + if (m_trcsr & M6801_TRCSR_TE) { - case IO_P1DDR: - data = m_port_ddr[0]; - break; + data = (data & 0xef) | (m_tx << 4); + ddr |= 0x10; + } + if ((m_tcsr3 & 0x0c) != 0) + { + data = (data & 0xbf) | (m_tout3 << 6); + ddr |= 0x40; + } - case IO_P2DDR: - data = m_port_ddr[1]; - break; + m_out_port_func[1](0, data, ddr); +} - case IO_P1DATA: - if(m_port_ddr[0] == 0xff) - data = m_port_data[0]; - else - data = (m_in_port_func[0]() & (m_port_ddr[0] ^ 0xff)) - | (m_port_data[0] & m_port_ddr[0]); - break; +void m6801_cpu_device::p2_ddr_w(u8 data) +{ + LOGPORT("Port 2 Data Direction Register: %02x\n", data); - case IO_P2DATA: - if(m_port_ddr[1] == 0xff) - data = m_port_data[1]; - else - data = (m_in_port_func[1]() & (m_port_ddr[1] ^ 0xff)) - | (m_port_data[1] & m_port_ddr[1]); - break; + if (m_port_ddr[1] != data) + { + m_port_ddr[1] = data; + write_port2(); + } +} - case IO_P3DDR: - data = 0xff; - break; +void hd6301x_cpu_device::p2_ddr_2bit_w(u8 data) +{ + // HD6301X DDR2 is 2-bit (it is 8-bit again on HD6301Y) + hd6301_cpu_device::p2_ddr_w((BIT(data, 1) ? 0xfe : 0x00) | (data & 0x01)); +} - case IO_P4DDR: - data = m_port_ddr[3]; - break; +u8 m6801_cpu_device::p2_data_r() +{ + u8 ddr = m_port_ddr[1] & ~m_port_ddr_override[1]; - case IO_P3DATA: - if (!machine().side_effects_disabled()) - { - if (m_p3csr_is3_flag_read) - { - LOGPORT("Cleared IS3\n"); - m_p3csr &= ~M6801_P3CSR_IS3_FLAG; - m_p3csr_is3_flag_read = 0; - } + if (ddr == 0xff) + return m_port_data[1]; + else + return (m_in_port_func[1]() & ~ddr) | (m_port_data[1] & ddr); +} - if (!(m_p3csr & M6801_P3CSR_OSS)) - { - set_os3(ASSERT_LINE); - } - } +void m6801_cpu_device::p2_data_w(u8 data) +{ + LOGPORT("Port 2 Data Register: %02x\n", data); - if ((m_p3csr & M6801_P3CSR_LE) || (m_port_ddr[2] == 0xff)) - data = m_port_data[2]; - else - data = (m_in_port_func[2]() & (m_port_ddr[2] ^ 0xff)) - | (m_port_data[2] & m_port_ddr[2]); + m_port_data[1] = data; + m_port2_written = true; + write_port2(); +} - if (!machine().side_effects_disabled()) - { - m_port3_latched = 0; - if (!(m_p3csr & M6801_P3CSR_OSS)) - { - set_os3(CLEAR_LINE); - } - } - break; +void m6801_cpu_device::set_os3(int state) +{ + LOG("OS3: %u\n", state); - case IO_P4DATA: - if(m_port_ddr[3] == 0xff) - data = m_port_data[3]; - else - data = (m_in_port_func[3]() & (m_port_ddr[3] ^ 0xff)) - | (m_port_data[3] & m_port_ddr[3]); - break; + m_out_sc2_func(state); +} - case IO_TCSR: - m_pending_tcsr = 0; - data = m_tcsr; - break; +void m6801_cpu_device::p3_ddr_w(u8 data) +{ + LOGPORT("Port 3 Data Direction Register: %02x\n", data); - case IO_CH: - if(!(m_pending_tcsr&TCSR_TOF) && !machine().side_effects_disabled()) - { - m_tcsr &= ~TCSR_TOF; - MODIFIED_tcsr; - } - data = m_counter.b.h; - break; + if (m_port_ddr[2] != data) + { + m_port_ddr[2] = data; + m_out_port_func[2](0, (m_port_data[2] & m_port_ddr[2]) | (m_port_ddr[2] ^ 0xff), m_port_ddr[2]); + } +} - case IO_CL: - data = m_counter.b.l; - // HACK there should be a break here, but Coleco Adam won't boot with it present, proper fix required to the free-running counter +void hd6301x_cpu_device::p3_ddr_1bit_w(u8 data) +{ + // HD6301X/Y DDR3 is 1-bit + hd6301_cpu_device::p3_ddr_w(BIT(data, 0) ? 0xff : 0x00); +} - case IO_OCRH: - if(!(m_pending_tcsr&TCSR_OCF) && !machine().side_effects_disabled()) +u8 m6801_cpu_device::p3_data_r() +{ + if (!machine().side_effects_disabled()) + { + if (m_pending_isf_clear) { - m_tcsr &= ~TCSR_OCF; - MODIFIED_tcsr; + LOGPORT("Cleared IS3\n"); + m_p3csr &= ~M6801_P3CSR_IS3_FLAG; + m_pending_isf_clear = false; } - data = m_output_compare.b.h; - break; - case IO_OCRL: - if(!(m_pending_tcsr&TCSR_OCF) && !machine().side_effects_disabled()) + if (!(m_p3csr & M6801_P3CSR_OSS)) { - m_tcsr &= ~TCSR_OCF; - MODIFIED_tcsr; + set_os3(ASSERT_LINE); } - data = m_output_compare.b.l; - break; + } - case IO_ICRH: - if(!(m_pending_tcsr&TCSR_ICF) && !machine().side_effects_disabled()) - { - m_tcsr &= ~TCSR_ICF; - MODIFIED_tcsr; - } - data = (m_input_capture >> 0) & 0xff; - break; + u8 data, ddr = m_port_ddr[2] & ~m_port_ddr_override[2]; - case IO_ICRL: - data = (m_input_capture >> 8) & 0xff; - break; + if ((m_p3csr & M6801_P3CSR_LE) || (ddr == 0xff)) + data = m_port_data[2]; + else + data = (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr); + + if (!machine().side_effects_disabled()) + { + m_port3_latched = 0; - case IO_P3CSR: - if ((m_p3csr & M6801_P3CSR_IS3_FLAG) && !machine().side_effects_disabled()) + if (!(m_p3csr & M6801_P3CSR_OSS)) { - m_p3csr_is3_flag_read = 1; + set_os3(CLEAR_LINE); } + } - data = m_p3csr; - break; + return data; +} - case IO_RMCR: - data = m_rmcr; - break; +void m6801_cpu_device::p3_data_w(u8 data) +{ + LOGPORT("Port 3 Data Register: %02x\n", data); - case IO_TRCSR: - if (!machine().side_effects_disabled()) - { - if (m_trcsr & M6801_TRCSR_TDRE) - { - m_trcsr_read_tdre = 1; - } + if (m_pending_isf_clear) + { + LOGPORT("Cleared IS3\n"); + m_p3csr &= ~M6801_P3CSR_IS3_FLAG; + m_pending_isf_clear = false; + } - if (m_trcsr & M6801_TRCSR_ORFE) - { - m_trcsr_read_orfe = 1; - } + if (m_p3csr & M6801_P3CSR_OSS) + { + set_os3(ASSERT_LINE); + } - if (m_trcsr & M6801_TRCSR_RDRF) - { - m_trcsr_read_rdrf = 1; - } - } + m_port_data[2] = data; + m_out_port_func[2](0, (m_port_data[2] & m_port_ddr[2]) | (m_port_ddr[2] ^ 0xff), m_port_ddr[2]); - data = m_trcsr; - break; + if (m_p3csr & M6801_P3CSR_OSS) + { + set_os3(CLEAR_LINE); + } +} - case IO_RDR: - if (!machine().side_effects_disabled()) - { - if (m_trcsr_read_orfe) - { - LOG("Cleared ORFE\n"); - m_trcsr_read_orfe = 0; - m_trcsr &= ~M6801_TRCSR_ORFE; - } +u8 hd6301x_cpu_device::p3_data_r() +{ + // no handshaking protocol + u8 ddr = m_port_ddr[2] & ~m_port_ddr_override[2]; - if (m_trcsr_read_rdrf) - { - LOG("Cleared RDRF\n"); - m_trcsr_read_rdrf = 0; - m_trcsr &= ~M6801_TRCSR_RDRF; - } - } + if (ddr == 0xff) + return m_port_data[2]; + else + return (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr); +} - data = m_rdr; - break; +void hd6301x_cpu_device::p3_data_w(u8 data) +{ + // no handshaking protocol + LOGPORT("Port 3 Data Register: %02x\n", data); - case IO_TDR: - data = m_tdr; - break; + m_port_data[2] = data; + m_out_port_func[2](0, (m_port_data[2] & m_port_ddr[2]) | (m_port_ddr[2] ^ 0xff), m_port_ddr[2]); +} - case IO_RCR: - data = m_ram_ctrl; - break; +u8 m6801_cpu_device::p3_csr_r() +{ + if ((m_p3csr & M6801_P3CSR_IS3_FLAG) && !machine().side_effects_disabled()) + { + m_pending_isf_clear = true; + } - case IO_CAAH: - case IO_CAAL: - case IO_TCR1: - case IO_TCR2: - case IO_TSR: - case IO_OCR2H: - case IO_OCR2L: - case IO_OCR3H: - case IO_OCR3L: - case IO_ICR2H: - case IO_ICR2L: - default: - logerror("PC %04x: warning - read from reserved internal register %02x\n", pc(),offset); + return m_p3csr; +} + +void m6801_cpu_device::p3_csr_w(u8 data) +{ + LOGPORT("Port 3 Control and Status Register: %02x\n", data); + + m_p3csr = data; +} + + +void m6801_cpu_device::p4_ddr_w(u8 data) +{ + LOGPORT("Port 4 Data Direction Register: %02x\n", data); + + if (m_port_ddr[3] != data) + { + m_port_ddr[3] = data; + m_out_port_func[3](0, (m_port_data[3] & m_port_ddr[3]) | (m_port_ddr[3] ^ 0xff), m_port_ddr[3]); + } +} + +u8 m6801_cpu_device::p4_data_r() +{ + u8 ddr = m_port_ddr[3] & ~m_port_ddr_override[3]; + + if (ddr == 0xff) + return m_port_data[3]; + else + return (m_in_port_func[3]() & ~ddr) | (m_port_data[3] & ddr); +} + +void m6801_cpu_device::p4_data_w(u8 data) +{ + LOGPORT("Port 4 Data Register: %02x\n", data); + + m_port_data[3] = data; + m_out_port_func[3](0, (m_port_data[3] & m_port_ddr[3]) | (m_port_ddr[3] ^ 0xff), m_port_ddr[3]); +} + +void hd6301y_cpu_device::p5_ddr_w(u8 data) +{ + LOGPORT("Port 5 Data Direction Register: %02x\n", data); + + if (m_portx_ddr[0] != data) + { + m_portx_ddr[0] = data; + m_out_portx_func[0](0, (m_portx_data[0] & m_portx_ddr[0]) | (m_portx_ddr[0] ^ 0xff), m_portx_ddr[0]); } +} + + +u8 hd6301x_cpu_device::p5_data_r() +{ + u8 data = m_in_portx_func[0](); + if (m_irq_state[HD6301_IRQ1_LINE]) + data &= 0xfe; + if (m_irq_state[HD6301_IRQ2_LINE]) + data &= 0xfd; + + // no DDR, read-only return data; } -WRITE8_MEMBER( m6801_cpu_device::m6801_io_w ) +u8 hd6301y_cpu_device::p5_data_r() { - switch (offset) + u8 ddr = m_portx_ddr[0] & ~m_portx_ddr_override[0]; + + if (ddr == 0xff) + return m_portx_data[0]; + else { - case IO_P1DDR: - LOGPORT("Port 1 Data Direction Register: %02x\n", data); + u8 data = hd6301x_cpu_device::p5_data_r(); - if (m_port_ddr[0] != data) - { - m_port_ddr[0] = data; - m_out_port_func[0]((m_port_data[0] & m_port_ddr[0]) | (m_port_ddr[0] ^ 0xff)); - } - break; + if (m_irq_state[M6801_IS3_LINE]) + data |= 0x10; - case IO_P2DDR: - LOGPORT("Port 2 Data Direction Register: %02x\n", data); + return (data & ~ddr) | (m_portx_data[0] & ddr); + } +} - if (m_port_ddr[1] != data) - { - m_port_ddr[1] = data; - write_port2(); - } - break; +void hd6301y_cpu_device::p5_data_w(u8 data) +{ + LOGPORT("Port 5 Data Register: %02x\n", data); - case IO_P1DATA: - LOGPORT("Port 1 Data Register: %02x\n", data); + m_portx_data[0] = data; + m_out_portx_func[0](0, (m_portx_data[0] & m_portx_ddr[0]) | (m_portx_ddr[0] ^ 0xff), m_portx_ddr[0]); +} - m_port_data[0] = data; - m_out_port_func[0]((m_port_data[0] & m_port_ddr[0]) | (m_port_ddr[0] ^ 0xff)); - break; - case IO_P2DATA: - LOGPORT("Port 2 Data Register: %02x\n", data); +void hd6301x_cpu_device::p6_ddr_w(u8 data) +{ + LOGPORT("Port 6 Data Direction Register: %02x\n", data); - m_port_data[1] = data; - m_port2_written = 1; - write_port2(); - break; + if (m_portx_ddr[1] != data) + { + m_portx_ddr[1] = data; + m_out_portx_func[1](0, (m_portx_data[1] & m_portx_ddr[1]) | (m_portx_ddr[1] ^ 0xff), m_portx_ddr[1]); + } +} - case IO_P3DDR: - LOGPORT("Port 3 Data Direction Register: %02x\n", data); +u8 hd6301x_cpu_device::p6_data_r() +{ + u8 ddr = m_portx_ddr[1] & ~m_portx_ddr_override[1]; - if (m_port_ddr[2] != data) - { - m_port_ddr[2] = data; - m_out_port_func[2]((m_port_data[2] & m_port_ddr[2]) | (m_port_ddr[2] ^ 0xff)); - } - break; + if (ddr == 0xff) + return m_portx_data[1]; + else + return (m_in_portx_func[1]() & ~ddr) | (m_portx_data[1] & ddr); +} - case IO_P4DDR: - LOGPORT("Port 4 Data Direction Register: %02x\n", data); +void hd6301x_cpu_device::p6_data_w(u8 data) +{ + LOGPORT("Port 6 Data Register: %02x\n", data); - if (m_port_ddr[3] != data) - { - m_port_ddr[3] = data; - m_out_port_func[3]((m_port_data[3] & m_port_ddr[3]) | (m_port_ddr[3] ^ 0xff)); - } - break; + m_portx_data[1] = data; + m_out_portx_func[1](0, (m_portx_data[1] & m_portx_ddr[1]) | (m_portx_ddr[1] ^ 0xff), m_portx_ddr[1]); +} - case IO_P3DATA: - LOGPORT("Port 3 Data Register: %02x\n", data); +u8 hd6301y_cpu_device::p6_data_r() +{ + if (!machine().side_effects_disabled()) + clear_pending_isf(); - if (m_p3csr_is3_flag_read) - { - LOGPORT("Cleared IS3\n"); - m_p3csr &= ~M6801_P3CSR_IS3_FLAG; - m_p3csr_is3_flag_read = 0; - } + return hd6301x_cpu_device::p6_data_r(); +} - if (m_p3csr & M6801_P3CSR_OSS) - { - set_os3(ASSERT_LINE); - } +void hd6301y_cpu_device::p6_data_w(u8 data) +{ + clear_pending_isf(); - m_port_data[2] = data; - m_out_port_func[2]((m_port_data[2] & m_port_ddr[2]) | (m_port_ddr[2] ^ 0xff)); + hd6301x_cpu_device::p6_data_w(data); +} - if (m_p3csr & M6801_P3CSR_OSS) - { - set_os3(CLEAR_LINE); - } - break; +void hd6301y_cpu_device::clear_pending_isf() +{ + // IS flag is cleared when reading/writing P6 after reading P6 CSR + if (m_pending_isf_clear) + { + m_p6csr &= 0x7f; + m_pending_isf_clear = false; + } +} - case IO_P4DATA: - LOGPORT("Port 4 Data Register: %02x\n", data); +u8 hd6301y_cpu_device::p6_csr_r() +{ + if (!machine().side_effects_disabled()) + m_pending_isf_clear = true; - m_port_data[3] = data; - m_out_port_func[3]((m_port_data[3] & m_port_ddr[3]) | (m_port_ddr[3] ^ 0xff)); - break; + return m_p6csr | 7; +} - case IO_TCSR: - LOG("Timer Control and Status Register: %02x\n", data); +void hd6301y_cpu_device::p6_csr_w(u8 data) +{ + LOGPORT("Port 6 Control/Status Register: %02x\n", data); - m_tcsr = data; - m_pending_tcsr &= m_tcsr; - MODIFIED_tcsr; - if( !(m_cc & 0x10) ) - m6800_check_irq2(); - break; + m_p6csr = (m_p6csr & 0x80) | (data & 0x7f); + check_irq2(); +} - case IO_CH: - LOG("Counter High Register: %02x\n", data); - m_latch09 = data & 0xff; /* 6301 only */ - CT = 0xfff8; - TOH = CTH; - MODIFIED_counters; - break; +u8 hd6301x_cpu_device::p7_data_r() +{ + return 0xe0 | m_portx_data[2]; +} - case IO_CL: /* 6301 only */ - LOG("Counter Low Register: %02x\n", data); +void hd6301x_cpu_device::p7_data_w(u8 data) +{ + data &= 0x1f; - CT = (m_latch09 << 8) | (data & 0xff); - TOH = CTH; - MODIFIED_counters; - break; + LOGPORT("Port 7 Data Register: %02x\n", data); - case IO_OCRH: - LOG("Output Compare High Register: %02x\n", data); + m_portx_data[2] = data; + m_out_portx_func[2](0, m_portx_data[2], 0x1f); +} - if( m_output_compare.b.h != data) - { - m_output_compare.b.h = data; - MODIFIED_counters; - } - break; - case IO_OCRL: - LOG("Output Compare Low Register: %02x\n", data); +u8 m6801_cpu_device::tcsr_r() +{ + if (!machine().side_effects_disabled()) + m_pending_tcsr = 0; + return m_tcsr; +} - if( m_output_compare.b.l != data) +void m6801_cpu_device::tcsr_w(u8 data) +{ + data &= 0x1f; + + LOGTIMER("Timer Control and Status Register: %02x\n", data); + + m_tcsr = data | (m_tcsr & 0xe0); + m_pending_tcsr &= m_tcsr; + check_irq2(); +} + +u8 m6801_cpu_device::ch_r() +{ + if (!(m_pending_tcsr & TCSR_TOF) && !machine().side_effects_disabled()) + { + m_tcsr &= ~TCSR_TOF; + } + return m_counter.b.h; +} + +u8 m6801_cpu_device::cl_r() +{ + return m_counter.b.l; +} + +void m6801_cpu_device::ch_w(u8 data) +{ + LOGTIMER("Counter High Register: %02x\n", data); + + m_latch09 = data & 0xff; /* 6301 only */ + CT = 0xfff8; + TOH = CTH; + modified_counters(); +} + +void m6801_cpu_device::cl_w(u8 data) +{ + LOGTIMER("Counter Low Register: %02x\n", data); + + CT = (m_latch09 << 8) | (data & 0xff); + TOH = CTH; + modified_counters(); +} + +u8 m6801_cpu_device::ocrh_r() +{ + return m_output_compare[0].b.h; +} + +u8 m6801_cpu_device::ocrl_r() +{ + return m_output_compare[0].b.l; +} + +void m6801_cpu_device::ocrh_w(u8 data) +{ + LOGTIMER("Output Compare High Register: %02x\n", data); + + if (!(m_pending_tcsr & TCSR_OCF)) + { + m_tcsr &= ~TCSR_OCF; + } + + if (m_output_compare[0].b.h != data) + { + m_output_compare[0].b.h = data; + modified_counters(); + } +} + +void m6801_cpu_device::ocrl_w(u8 data) +{ + LOGTIMER("Output Compare Low Register: %02x\n", data); + + if (!(m_pending_tcsr & TCSR_OCF)) + { + m_tcsr &= ~TCSR_OCF; + } + + if (m_output_compare[0].b.l != data) + { + m_output_compare[0].b.l = data; + modified_counters(); + } +} + +u8 m6801_cpu_device::icrh_r() +{ + if (!(m_pending_tcsr & TCSR_ICF) && !machine().side_effects_disabled()) + { + m_tcsr &= ~TCSR_ICF; + } + return (m_input_capture >> 0) & 0xff; +} + +u8 m6801_cpu_device::icrl_r() +{ + return (m_input_capture >> 8) & 0xff; +} + + +u8 m6801u4_cpu_device::tcr2_r() +{ + return m_tcr[1] | 0x03; +} + +void m6801u4_cpu_device::tcr2_w(u8 data) +{ + LOGTIMER("Timer Control Register 2: %02x\n", data); + + m_tcr[1] = data & 0xfc; + check_irq2(); +} + +u8 m6801u4_cpu_device::tsr_r() +{ + if (!machine().side_effects_disabled()) + { + m_pending_tcsr &= ~(TCSR_ICF | TCSR_OCF | TCSR_TOF); + m_pending_tsr = 0; + } + + return m_tsr | 0x03 | + ((m_tcsr & TCSR_ICF) ? TSR_ICF1 : 0) | + ((m_tcsr & TCSR_TOF) ? TSR_TOF : 0) | + ((m_tcsr & TCSR_OCF) ? TSR_OCF1 : 0); +} + +template<int N> +u8 m6801u4_cpu_device::ocr2h_r() +{ + return m_output_compare[N].b.h; +} + +template<int N> +u8 m6801u4_cpu_device::ocr2l_r() +{ + return m_output_compare[N].b.l; +} + +template<int N> +void m6801u4_cpu_device::ocr2h_w(u8 data) +{ + LOGTIMER("Output Compare High Register %d: %02x\n", N + 1, data); + + if (!(m_pending_tsr & (TSR_OCF2 * N))) + { + m_tsr &= ~(TSR_OCF2 * N); + } + + if (m_output_compare[N].b.h != data) + { + m_output_compare[N].b.h = data; + modified_counters(); + } +} + +template<int N> +void m6801u4_cpu_device::ocr2l_w(u8 data) +{ + LOGTIMER("Output Compare Low Register %d: %02x\n", N + 1, data); + + if (!(m_pending_tsr & (TSR_OCF2 * N))) + { + m_tsr &= ~(TSR_OCF2 * N); + } + + if (m_output_compare[N].b.l != data) + { + m_output_compare[N].b.l = data; + modified_counters(); + } +} + + +u8 hd6301x_cpu_device::tcsr2_r() +{ + if (!machine().side_effects_disabled()) + { + m_pending_tcsr &= ~(TCSR_ICF | TCSR_OCF); + m_pending_tcsr2 = 0; + } + return m_tcsr2 | (m_tcsr & (TCSR_ICF | TCSR_OCF)) | 0x10; +} + +void hd6301x_cpu_device::tcsr2_w(u8 data) +{ + LOGTIMER("Timer Control and Status Register 2: %02x\n", data); + + data &= TCSR2_OE1 | TCSR2_OE2 | TCSR2_OLVL2 | TCSR2_EOCI2; + m_tcsr2 = data | (m_tcsr2 & TCSR2_OCF2); + m_pending_tcsr2 &= m_tcsr2; + check_irq2(); +} + +u8 hd6301x_cpu_device::ocr2h_r() +{ + return m_output_compare[1].b.h; +} + +u8 hd6301x_cpu_device::ocr2l_r() +{ + return m_output_compare[1].b.l; +} + +void hd6301x_cpu_device::ocr2h_w(u8 data) +{ + LOGTIMER("Output Compare High Register 2: %02x\n", data); + + if (!(m_pending_tcsr2 & TCSR2_OCF2)) + { + m_tcsr2 &= ~TCSR2_OCF2; + } + + if (m_output_compare[1].b.h != data) + { + m_output_compare[1].b.h = data; + modified_counters(); + } +} + +void hd6301x_cpu_device::ocr2l_w(u8 data) +{ + LOGTIMER("Output Compare Low Register 2: %02x\n", data); + + if (!(m_pending_tcsr2 & TCSR2_OCF2)) + { + m_tcsr2 &= ~TCSR2_OCF2; + } + + if (m_output_compare[1].b.l != data) + { + m_output_compare[1].b.l = data; + modified_counters(); + } +} + + +void hd6301x_cpu_device::increment_t2cnt(int amount) +{ + while (amount--) + { + if (++m_t2cnt == ((m_tconr + 1) & 0xff)) { - m_output_compare.b.l = data; - MODIFIED_counters; + m_t2cnt = 0; + + if (BIT(m_tcsr3, 3)) + { + if (m_tout3 != BIT(m_tcsr3, 2)) + { + m_tout3 = BIT(m_tcsr3, 2); + m_port2_written = true; + write_port2(); + } + } + else if (BIT(m_tcsr3, 2)) + { + m_tout3 = !m_tout3; + m_port2_written = true; + write_port2(); + } + + if (BIT(m_rmcr, 5) && !m_use_ext_serclock) + sci_clock_internal(32); + + m_tcsr3 |= 0x80; + m_timer_next = 0; // HACK } - break; + } +} - case IO_ICRH: - case IO_ICRL: - case IO_RDR: - LOG("PC %04x: warning - write %02x to read only internal register %02x\n",pc(),data,offset); - break; +u8 hd6301x_cpu_device::t2cnt_r() +{ + return m_t2cnt; +} - case IO_P3CSR: - LOGPORT("Port 3 Control and Status Register: %02x\n", data); +void hd6301x_cpu_device::t2cnt_w(u8 data) +{ + m_t2cnt = data; + m_t2cnt_written = true; +} - m_p3csr = data; - break; +void hd6301x_cpu_device::tconr_w(u8 data) +{ + m_tconr = data; +} - case IO_RMCR: - LOG("Rate and Mode Control Register: %02x\n", data); +u8 hd6301x_cpu_device::tcsr3_r() +{ + return m_tcsr3; +} - set_rmcr(data); - break; +void hd6301x_cpu_device::tcsr3_w(u8 data) +{ + u8 tout3_last_enable = (m_tcsr3 & 0x0c) != 0; + + // Bit 5 does not exist and Bit 7 can only be written with 0 + m_tcsr3 = data & (0x5f | (m_tcsr3 & 0x80)); - case IO_TRCSR: - LOG("Transmit/Receive Control and Status Register: %02x\n", data); + if (m_tout3 && !BIT(data, 4)) + { + m_tout3 = false; + write_port2(); + } + else if (tout3_last_enable ? (data & 0x0c) == 0 : (data & 0x0c) != 0) + { + m_port2_written = true; + write_port2(); + } - if ((data & M6801_TRCSR_TE) && !(m_trcsr & M6801_TRCSR_TE)) + check_irq2(); +} + + +u8 m6801_cpu_device::sci_rmcr_r() +{ + return m_rmcr; +} + +void m6801_cpu_device::sci_rmcr_w(u8 data) +{ + LOGSER("SCI Rate and Mode Control Register: %02x\n", data); + + set_rmcr(data); +} + +u8 m6801_cpu_device::sci_trcsr_r() +{ + if (!machine().side_effects_disabled()) + { + if (m_trcsr & M6801_TRCSR_TDRE) { - m_txstate = M6801_TX_STATE_INIT; - m_txbits = 0; - m_tx = 1; + m_trcsr_read_tdre = 1; } - if ((data & M6801_TRCSR_RE) && !(m_trcsr & M6801_TRCSR_RE)) + if (m_trcsr & M6801_TRCSR_ORFE) { - m_rxbits = 0; + m_trcsr_read_orfe = 1; } - m_trcsr = (m_trcsr & 0xe0) | (data & 0x1f); - break; - - case IO_TDR: - LOGTX("Transmit Data Register: %02x\n", data); - - if (m_trcsr_read_tdre) + if (m_trcsr & M6801_TRCSR_RDRF) { - m_trcsr_read_tdre = 0; - m_trcsr &= ~M6801_TRCSR_TDRE; + m_trcsr_read_rdrf = 1; } - m_tdr = data; - break; + } - case IO_RCR: - LOG("RAM Control Register: %02x\n", data); + return m_trcsr; +} - m_ram_ctrl = data; - break; +void m6801_cpu_device::sci_trcsr_w(u8 data) +{ + LOGSER("SCI Transmit/Receive Control and Status Register: %02x\n", data); - case IO_CAAH: - case IO_CAAL: - case IO_TCR1: - case IO_TCR2: - case IO_TSR: - case IO_OCR2H: - case IO_OCR2L: - case IO_OCR3H: - case IO_OCR3L: - case IO_ICR2H: - case IO_ICR2L: - default: - logerror("PC %04x: warning - write %02x to reserved internal register %02x\n", pc(),data,offset); - break; + if ((data & M6801_TRCSR_TE) && !(m_trcsr & M6801_TRCSR_TE)) + { + m_txstate = M6801_TX_STATE_INIT; + m_txbits = 0; + m_tx = 1; + } + + if ((data & M6801_TRCSR_RE) && !(m_trcsr & M6801_TRCSR_RE)) + { + m_rxbits = 0; } -} + m_trcsr = (m_trcsr & 0xe0) | (data & 0x1f); +} -void m6801_cpu_device::m6801_clock_serial() +u8 m6801_cpu_device::sci_rdr_r() { - if (m_use_ext_serclock) + if (!machine().side_effects_disabled()) { - m_ext_serclock++; + if (m_trcsr_read_orfe) + { + LOGSER("Cleared ORFE\n"); + m_trcsr_read_orfe = 0; + m_trcsr &= ~M6801_TRCSR_ORFE; + } - if (m_ext_serclock >= 8) + if (m_trcsr_read_rdrf) { - m_ext_serclock = 0; - serial_transmit(); - serial_receive(); + LOGSER("Cleared RDRF\n"); + m_trcsr_read_rdrf = 0; + m_trcsr &= ~M6801_TRCSR_RDRF; } } + + return m_rdr; +} + +void m6801_cpu_device::sci_tdr_w(u8 data) +{ + LOGSER("SCI Transmit Data Register: $%02x/%d\n", data, data); + + if (m_trcsr_read_tdre) + { + m_trcsr_read_tdre = 0; + m_trcsr &= ~M6801_TRCSR_TDRE; + } + m_tdr = data; } + +u8 m6801_cpu_device::rcr_r() +{ + return m_ram_ctrl | 0x3f; +} + +u8 hd6301x_cpu_device::rcr_r() +{ + return m_ram_ctrl | 0x30; +} + +u8 hd6301y_cpu_device::rcr_r() +{ + // no unused bits + return m_ram_ctrl; +} + +void m6801_cpu_device::rcr_w(u8 data) +{ + LOG("RAM Control Register: %02x\n", data); + + m_ram_ctrl = data; +} + +void hd6301x_cpu_device::rcr_w(u8 data) +{ + m6801_cpu_device::rcr_w(data); + check_irq_lines(); +} + +void hd6301y_cpu_device::rcr_w(u8 data) +{ + hd6301x_cpu_device::rcr_w(data); + + // software standby mode + if (~data & 0x20) + execute_set_input(M6801_STBY_LINE, ASSERT_LINE); +} + +u8 m6801_cpu_device::ff_r() +{ + return 0xff; +} + + std::unique_ptr<util::disasm_interface> m6801_cpu_device::create_disassembler() { return std::make_unique<m680x_disassembler>(6801); @@ -1275,17 +2582,17 @@ std::unique_ptr<util::disasm_interface> m6803_cpu_device::create_disassembler() return std::make_unique<m680x_disassembler>(6803); } -std::unique_ptr<util::disasm_interface> hd6301_cpu_device::create_disassembler() +std::unique_ptr<util::disasm_interface> m6803e_cpu_device::create_disassembler() { - return std::make_unique<m680x_disassembler>(6301); + return std::make_unique<m680x_disassembler>(6803); } -std::unique_ptr<util::disasm_interface> hd63701_cpu_device::create_disassembler() +std::unique_ptr<util::disasm_interface> hd6301_cpu_device::create_disassembler() { - return std::make_unique<m680x_disassembler>(63701); + return std::make_unique<m680x_disassembler>(6301); } -void hd63701_cpu_device::TAKE_TRAP() +void hd6301_cpu_device::take_trap() { - enter_interrupt("take TRAP\n",0xffee); + enter_interrupt("TRAP", 0xffee); } |