summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6800/m6801.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6800/m6801.cpp')
-rw-r--r--src/devices/cpu/m6800/m6801.cpp2503
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(&region->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);
}