summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6502
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6502')
-rw-r--r--src/devices/cpu/m6502/deco16.cpp7
-rw-r--r--src/devices/cpu/m6502/deco16.h2
-rw-r--r--src/devices/cpu/m6502/dm6502.lst2
-rw-r--r--src/devices/cpu/m6502/dm740.lst64
-rw-r--r--src/devices/cpu/m6502/dr65c19.lst20
-rw-r--r--src/devices/cpu/m6502/drp2a03.lst (renamed from src/devices/cpu/m6502/dn2a03.lst)2
-rw-r--r--src/devices/cpu/m6502/dw65c02.lst (renamed from src/devices/cpu/m6502/dm65c02.lst)2
-rw-r--r--src/devices/cpu/m6502/dw65c02s.lst20
-rw-r--r--src/devices/cpu/m6502/g65sc02.cpp46
-rw-r--r--src/devices/cpu/m6502/g65sc02.h54
-rw-r--r--src/devices/cpu/m6502/gew12.cpp229
-rw-r--r--src/devices/cpu/m6502/gew12.h78
-rw-r--r--src/devices/cpu/m6502/gew7.cpp216
-rw-r--r--src/devices/cpu/m6502/gew7.h74
-rw-r--r--src/devices/cpu/m6502/m3745x.cpp59
-rw-r--r--src/devices/cpu/m6502/m3745x.h39
-rw-r--r--src/devices/cpu/m6502/m37640.cpp31
-rw-r--r--src/devices/cpu/m6502/m37640.h38
-rw-r--r--src/devices/cpu/m6502/m4510.cpp118
-rw-r--r--src/devices/cpu/m6502/m4510.h39
-rw-r--r--src/devices/cpu/m6502/m50734.cpp473
-rw-r--r--src/devices/cpu/m6502/m50734.h160
-rw-r--r--src/devices/cpu/m6502/m5074x.cpp342
-rw-r--r--src/devices/cpu/m6502/m5074x.h106
-rw-r--r--src/devices/cpu/m6502/m6500_1.cpp98
-rw-r--r--src/devices/cpu/m6502/m6500_1.h59
-rw-r--r--src/devices/cpu/m6502/m6502.cpp192
-rw-r--r--src/devices/cpu/m6502/m6502.h94
-rw-r--r--src/devices/cpu/m6502/m6502.txt18
-rw-r--r--src/devices/cpu/m6502/m6502d.cpp22
-rw-r--r--src/devices/cpu/m6502/m6502d.h4
-rwxr-xr-xsrc/devices/cpu/m6502/m6502make.py157
-rw-r--r--src/devices/cpu/m6502/m6502mcu.h37
-rw-r--r--src/devices/cpu/m6502/m6502mcu.ipp75
-rw-r--r--src/devices/cpu/m6502/m6503.cpp25
-rw-r--r--src/devices/cpu/m6502/m6503.h28
-rw-r--r--src/devices/cpu/m6502/m6504.cpp48
-rw-r--r--src/devices/cpu/m6502/m6504.h23
-rw-r--r--src/devices/cpu/m6502/m6507.cpp48
-rw-r--r--src/devices/cpu/m6502/m6507.h23
-rw-r--r--src/devices/cpu/m6502/m6509.cpp59
-rw-r--r--src/devices/cpu/m6502/m6509.h18
-rw-r--r--src/devices/cpu/m6502/m6510.cpp118
-rw-r--r--src/devices/cpu/m6502/m6510.h35
-rw-r--r--src/devices/cpu/m6502/m6510t.cpp4
-rw-r--r--src/devices/cpu/m6502/m65c02.cpp33
-rw-r--r--src/devices/cpu/m6502/m65ce02.cpp15
-rw-r--r--src/devices/cpu/m6502/m65ce02.h8
-rw-r--r--src/devices/cpu/m6502/m65sc02.cpp19
-rw-r--r--src/devices/cpu/m6502/m65sc02.h29
-rw-r--r--src/devices/cpu/m6502/m740.cpp52
-rw-r--r--src/devices/cpu/m6502/m740.h66
-rw-r--r--src/devices/cpu/m6502/m7501.cpp4
-rw-r--r--src/devices/cpu/m6502/m8502.cpp4
-rw-r--r--src/devices/cpu/m6502/n2a03.cpp87
-rw-r--r--src/devices/cpu/m6502/n2a03.h74
-rw-r--r--src/devices/cpu/m6502/odeco16.lst28
-rw-r--r--src/devices/cpu/m6502/om6502.lst556
-rw-r--r--src/devices/cpu/m6502/om6509.lst2
-rw-r--r--src/devices/cpu/m6502/om6510.lst7
-rw-r--r--src/devices/cpu/m6502/om65ce02.lst451
-rw-r--r--src/devices/cpu/m6502/om740.lst1770
-rw-r--r--src/devices/cpu/m6502/or65c19.lst488
-rw-r--r--src/devices/cpu/m6502/orp2a03.lst (renamed from src/devices/cpu/m6502/on2a03.lst)100
-rw-r--r--src/devices/cpu/m6502/ow65c02.lst (renamed from src/devices/cpu/m6502/om65c02.lst)286
-rw-r--r--src/devices/cpu/m6502/ow65c02s.lst968
-rw-r--r--src/devices/cpu/m6502/oxavix.lst209
-rw-r--r--src/devices/cpu/m6502/oxavix2000.lst201
-rw-r--r--src/devices/cpu/m6502/r65c02.cpp22
-rw-r--r--src/devices/cpu/m6502/r65c02.h20
-rw-r--r--src/devices/cpu/m6502/r65c19.cpp290
-rw-r--r--src/devices/cpu/m6502/r65c19.h165
-rw-r--r--src/devices/cpu/m6502/r65c19d.cpp10
-rw-r--r--src/devices/cpu/m6502/r65c19d.h21
-rw-r--r--src/devices/cpu/m6502/rp2a03.cpp99
-rw-r--r--src/devices/cpu/m6502/rp2a03.h91
-rw-r--r--src/devices/cpu/m6502/rp2a03d.cpp (renamed from src/devices/cpu/m6502/n2a03d.cpp)8
-rw-r--r--src/devices/cpu/m6502/rp2a03d.h (renamed from src/devices/cpu/m6502/n2a03d.h)12
-rw-r--r--src/devices/cpu/m6502/st2204.cpp728
-rw-r--r--src/devices/cpu/m6502/st2204.h163
-rw-r--r--src/devices/cpu/m6502/st2205u.cpp1354
-rw-r--r--src/devices/cpu/m6502/st2205u.h318
-rw-r--r--src/devices/cpu/m6502/st2xxx.cpp914
-rw-r--r--src/devices/cpu/m6502/st2xxx.h299
-rw-r--r--src/devices/cpu/m6502/w65c02.cpp33
-rw-r--r--src/devices/cpu/m6502/w65c02.h (renamed from src/devices/cpu/m6502/m65c02.h)24
-rw-r--r--src/devices/cpu/m6502/w65c02d.cpp (renamed from src/devices/cpu/m6502/m65c02d.cpp)10
-rw-r--r--src/devices/cpu/m6502/w65c02d.h (renamed from src/devices/cpu/m6502/m65c02d.h)14
-rw-r--r--src/devices/cpu/m6502/w65c02s.cpp33
-rw-r--r--src/devices/cpu/m6502/w65c02s.h71
-rw-r--r--src/devices/cpu/m6502/xavix.cpp102
-rw-r--r--src/devices/cpu/m6502/xavix.h50
-rw-r--r--src/devices/cpu/m6502/xavix2000.cpp14
-rw-r--r--src/devices/cpu/m6502/xavix2000.h2
94 files changed, 11600 insertions, 2130 deletions
diff --git a/src/devices/cpu/m6502/deco16.cpp b/src/devices/cpu/m6502/deco16.cpp
index ae99a32418d..d2437f03499 100644
--- a/src/devices/cpu/m6502/deco16.cpp
+++ b/src/devices/cpu/m6502/deco16.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- deco16.c
+ deco16.cpp
6502, reverse-engineered DECO variant
@@ -33,10 +33,7 @@ std::unique_ptr<util::disasm_interface> deco16_device::create_disassembler()
void deco16_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_default_nd>();
- else
- mintf = std::make_unique<mi_default_normal>();
+ mintf = std::make_unique<mi_default>();
init();
diff --git a/src/devices/cpu/m6502/deco16.h b/src/devices/cpu/m6502/deco16.h
index 63494f6b1d4..60c0e2a4eaf 100644
--- a/src/devices/cpu/m6502/deco16.h
+++ b/src/devices/cpu/m6502/deco16.h
@@ -28,7 +28,7 @@ protected:
address_space_config io_config;
virtual space_config_vector memory_space_config() const override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
#define O(o) void o ## _full(); void o ## _partial()
diff --git a/src/devices/cpu/m6502/dm6502.lst b/src/devices/cpu/m6502/dm6502.lst
index 654a2f1fe74..99f3a05edb9 100644
--- a/src/devices/cpu/m6502/dm6502.lst
+++ b/src/devices/cpu/m6502/dm6502.lst
@@ -1,6 +1,6 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
-# m6502_family_device - 6502, 6504
+# m6502_family_device - 6502, 6503, 6504, 6507
brk_imp ora_idx kil_non slo_idx nop_zpg ora_zpg asl_zpg slo_zpg php_imp ora_imm asl_acc anc_imm nop_aba ora_aba asl_aba slo_aba
bpl_rel ora_idy kil_non slo_idy nop_zpx ora_zpx asl_zpx slo_zpx clc_imp ora_aby nop_imp slo_aby nop_abx ora_abx asl_abx slo_abx
jsr_adr and_idx kil_non rla_idx bit_zpg and_zpg rol_zpg rla_zpg plp_imp and_imm rol_acc anc_imm bit_aba and_aba rol_aba rla_aba
diff --git a/src/devices/cpu/m6502/dm740.lst b/src/devices/cpu/m6502/dm740.lst
index 04f67738dc9..c1cd3dba6e6 100644
--- a/src/devices/cpu/m6502/dm740.lst
+++ b/src/devices/cpu/m6502/dm740.lst
@@ -1,36 +1,36 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
# m740 device
-brk740_imp ora_idx kil_non bbs_bar nop_zpg ora_zpg asl_zpg bbs_bzr php_imp ora_imm asl_acc seb_bac nop_aba ora_aba asl_aba seb_biz
-bpl_rel ora_idy clt_imp bbc_bar nop_zpx ora_zpx asl_zpx bbc_bzr clc_imp ora_aby dec_acc clb_bac nop_abx ora_abx asl_abx clb_biz
-jsr_adr and_idx jsr_spg bbs_bar bit_zpg and_zpg rol_zpg bbs_bzr plp_imp and_imm rol_acc seb_bac bit_aba and_aba rol_aba seb_biz
-bmi_rel and_idy set_imp bbc_bar nop_zpx and_zpx rol_zpx bbc_bzr sec_imp and_aby inc_acc clb_bac ldm_imz and_abx rol_abx clb_biz
-rti_imp eor_idx kil_non bbs_bar com_zpg eor_zpg lsr_zpg bbs_bzr pha_imp eor_imm lsr_acc seb_bac jmp_adr eor_aba lsr_aba seb_biz
-bvc_rel eor_idy kil_non bbc_bar nop_zpx eor_zpx lsr_zpx bbc_bzr cli_imp eor_aby nop_imp clb_bac nop_abx eor_abx lsr_abx clb_biz
-rts_imp adc_idx kil_non bbs_bar nop_zpg adc_zpg ror_zpg bbs_bzr pla_imp adc_imm ror_acc seb_bac jmp_ind adc_aba ror_aba seb_biz
-bvs_rel adc_idy kil_non bbc_bar nop_zpx adc_zpx ror_zpx bbc_bzr sei_imp adc_aby nop_imp clb_bac nop_abx adc_abx ror_abx clb_biz
-bra_rel sta_idx rrf_zpg bbs_bar sty_zpg sta_zpg stx_zpg bbs_bzr dey_imp nop_imm txa_imp seb_bac sty_aba sta_aba stx_aba seb_biz
-bcc_rel sta_idy kil_non bbc_bar sty_zpx sta_zpx stx_zpy bbc_bzr tya_imp sta_aby txs_imp clb_bac shy_abx sta_abx shx_aby clb_biz
-ldy_imm lda_idx ldx_imm bbs_bar ldy_zpg lda_zpg ldx_zpg bbs_bzr tay_imp lda_imm tax_imp seb_bac ldy_aba lda_aba ldx_aba seb_biz
-bcs_rel lda_idy jmp_zpi bbc_bar ldy_zpx lda_zpx ldx_zpy bbc_bzr clv_imp lda_aby tsx_imp clb_bac ldy_abx lda_abx ldx_aby clb_biz
-cpy_imm cmp_idx nop_imm bbs_bar cpy_zpg cmp_zpg dec_zpg bbs_bzr iny_imp cmp_imm dex_imp seb_bac cpy_aba cmp_aba dec_aba seb_biz
-bne_rel cmp_idy kil_non bbc_bar nop_zpx cmp_zpx dec_zpx bbc_bzr cld_imp cmp_aby nop_imp clb_bac nop_abx cmp_abx dec_abx clb_biz
-cpx_imm sbc_idx nop_imm bbs_bar cpx_zpg sbc_zpg inc_zpg bbs_bzr inx_imp sbc_imm nop_imp seb_bac cpx_aba sbc_aba inc_aba seb_biz
-beq_rel sbc_idy kil_non bbc_bar nop_zpx sbc_zpx inc_zpx bbc_bzr sed_imp sbc_aby nop_imp clb_bac nop_abx sbc_abx inc_abx clb_biz
-brk740_imp ort_idx kil_non bbs_bar nop_zpg ort_zpg asl_zpg bbs_bzr php_imp ort_imm asl_acc seb_bac nop_aba ort_aba asl_aba seb_biz
-bpl_rel ort_idy clt_imp bbc_bar nop_zpx ort_zpx asl_zpx bbc_bzr clc_imp ort_aby dect_acc clb_bac nop_abx ort_abx asl_abx clb_biz
-jsr_adr andt_idx jsr_spg bbs_bar bit_zpg andt_zpg rol_zpg bbs_bzr plp_imp andt_imm rol_acc seb_bac bit_aba andt_aba rol_aba seb_biz
-bmi_rel andt_idy set_imp bbc_bar nop_zpx andt_zpx rol_zpx bbc_bzr sec_imp andt_aby inct_acc clb_bac ldm_imz andt_abx rol_abx clb_biz
-rti_imp eort_idx kil_non bbs_bar com_zpg eort_zpg lsr_zpg bbs_bzr pha_imp eort_imm lsr_acc seb_bac jmp_adr eort_aba lsr_aba seb_biz
-bvc_rel eort_idy kil_non bbc_bar nop_zpx eort_zpx lsr_zpx bbc_bzr cli_imp eort_aby nop_imp clb_bac nop_abx eort_abx lsr_abx clb_biz
-rts_imp adct_idx kil_non bbs_bar nop_zpg adct_zpg ror_zpg bbs_bzr pla_imp adct_imm ror_acc seb_bac jmp_ind adct_aba ror_aba seb_biz
-bvs_rel adct_idy kil_non bbc_bar nop_zpx adct_zpx ror_zpx bbc_bzr sei_imp adct_aby nop_imp clb_bac nop_abx adct_abx ror_abx clb_biz
-bra_rel sta_idx rrf_zpg bbs_bar sty_zpg sta_zpg stx_zpg bbs_bzr dey_imp nop_imm txa_imp seb_bac sty_aba sta_aba stx_aba seb_biz
-bcc_rel sta_idy kil_non bbc_bar sty_zpx sta_zpx stx_zpy bbc_bzr tya_imp sta_aby txs_imp clb_bac shy_abx sta_abx shx_aby clb_biz
+brk_m_imp ora_m_idx jsr_zpi bbs_bar nop_zpg ora_zpg asl_m_zpg bbs_bzr php_imp ora_imm asl_acc seb_bac nop_aba ora_aba asl_m_aba seb_biz
+bpl_m_rel ora_m_idy clt_imp bbc_bar nop_zpx ora_m_zpx asl_m_zpx bbc_bzr clc_imp ora_m_aby dec_acc clb_bac nop_abx ora_m_abx asl_m_abx clb_biz
+jsr_m_adr and_m_idx jsr_spg bbs_bar bit_zpg and_zpg rol_m_zpg bbs_bzr plp_m_imp and_imm rol_acc seb_bac bit_aba and_aba rol_m_aba seb_biz
+bmi_m_rel and_m_idy set_imp bbc_bar nop_zpx and_m_zpx rol_m_zpx bbc_bzr sec_imp and_m_aby inc_acc clb_bac ldm_imz and_m_abx rol_m_abx clb_biz
+rti_m_imp eor_m_idx stp_imp bbs_bar com_zpg eor_zpg lsr_m_zpg bbs_bzr pha_imp eor_imm lsr_acc seb_bac jmp_adr eor_aba lsr_m_aba seb_biz
+bvc_m_rel eor_m_idy kil_non bbc_bar nop_zpx eor_m_zpx lsr_m_zpx bbc_bzr cli_imp eor_m_aby nop_imp clb_bac nop_abx eor_m_abx lsr_m_abx clb_biz
+rts_m_imp adc_m_idx kil_non bbs_bar tst_zpg adc_zpg ror_m_zpg bbs_bzr pla_m_imp adc_imm ror_acc seb_bac jmp_ind adc_aba ror_m_aba seb_biz
+bvs_m_rel adc_m_idy kil_non bbc_bar nop_zpx adc_m_zpx ror_m_zpx bbc_bzr sei_imp adc_m_aby nop_imp clb_bac nop_abx adc_m_abx ror_m_abx clb_biz
+bra_rel sta_m_idx rrf_zpg bbs_bar sty_m_zpg sta_m_zpg stx_m_zpg bbs_bzr dey_imp nop_imm txa_imp seb_bac sty_m_aba sta_m_aba stx_m_aba seb_biz
+bcc_m_rel sta_m_idy kil_non bbc_bar sty_m_zpx sta_m_zpx stx_m_zpy bbc_bzr tya_imp sta_m_aby txs_imp clb_bac shy_abx sta_m_abx shx_aby clb_biz
+ldy_imm lda_m_idx ldx_imm bbs_bar ldy_zpg lda_zpg ldx_zpg bbs_bzr tay_imp lda_imm tax_imp seb_bac ldy_aba lda_aba ldx_aba seb_biz
+bcs_m_rel lda_m_idy jmp_zpi bbc_bar ldy_m_zpx lda_m_zpx ldx_m_zpy bbc_bzr clv_imp lda_m_aby tsx_imp clb_bac ldy_m_abx lda_m_abx ldx_m_aby clb_biz
+cpy_imm cmp_m_idx wit_imp bbs_bar cpy_zpg cmp_zpg dec_m_zpg bbs_bzr iny_imp cmp_imm dex_imp seb_bac cpy_aba cmp_aba dec_m_aba seb_biz
+bne_m_rel cmp_m_idy kil_non bbc_bar nop_zpx cmp_m_zpx dec_m_zpx bbc_bzr cld_imp cmp_m_aby nop_imp clb_bac nop_abx cmp_m_abx dec_m_abx clb_biz
+cpx_imm sbc_m_idx nop_imm bbs_bar cpx_zpg sbc_zpg inc_m_zpg bbs_bzr inx_imp sbc_imm nop_imp seb_bac cpx_aba sbc_aba inc_m_aba seb_biz
+beq_m_rel sbc_m_idy kil_non bbc_bar nop_zpx sbc_zpx inc_m_zpx bbc_bzr sed_imp sbc_m_aby nop_imp clb_bac nop_abx sbc_m_abx inc_m_abx clb_biz
+brk_m_imp ort_idx jsr_zpi bbs_bar nop_zpg ort_zpg asl_m_zpg bbs_bzr php_imp ort_imm asl_acc seb_bac nop_aba ort_aba asl_m_aba seb_biz
+bpl_m_rel ort_idy clt_imp bbc_bar nop_zpx ort_zpx asl_m_zpx bbc_bzr clc_imp ort_aby dec_acc clb_bac nop_abx ort_abx asl_m_abx clb_biz
+jsr_m_adr andt_idx jsr_spg bbs_bar bit_zpg andt_zpg rol_m_zpg bbs_bzr plp_m_imp andt_imm rol_acc seb_bac bit_aba andt_aba rol_m_aba seb_biz
+bmi_m_rel andt_idy set_imp bbc_bar nop_zpx andt_zpx rol_m_zpx bbc_bzr sec_imp andt_aby inc_acc clb_bac ldm_imz andt_abx rol_m_abx clb_biz
+rti_m_imp eort_idx stp_imp bbs_bar com_zpg eort_zpg lsr_m_zpg bbs_bzr pha_imp eort_imm lsr_acc seb_bac jmp_adr eort_aba lsr_m_aba seb_biz
+bvc_m_rel eort_idy kil_non bbc_bar nop_zpx eort_zpx lsr_m_zpx bbc_bzr cli_imp eort_aby nop_imp clb_bac nop_abx eort_abx lsr_m_abx clb_biz
+rts_m_imp adct_idx kil_non bbs_bar tst_zpg adct_zpg ror_m_zpg bbs_bzr pla_m_imp adct_imm ror_acc seb_bac jmp_ind adct_aba ror_m_aba seb_biz
+bvs_m_rel adct_idy kil_non bbc_bar nop_zpx adct_zpx ror_m_zpx bbc_bzr sei_imp adct_aby nop_imp clb_bac nop_abx adct_abx ror_m_abx clb_biz
+bra_rel sta_m_idx rrf_zpg bbs_bar sty_m_zpg sta_m_zpg stx_m_zpg bbs_bzr dey_imp nop_imm txa_imp seb_bac sty_m_aba sta_m_aba stx_m_aba seb_biz
+bcc_m_rel sta_m_idy kil_non bbc_bar sty_m_zpx sta_m_zpx stx_m_zpy bbc_bzr tya_imp sta_m_aby txs_imp clb_bac shy_abx sta_m_abx shx_aby clb_biz
ldy_imm ldt_idx ldx_imm bbs_bar ldy_zpg ldt_zpg ldx_zpg bbs_bzr tay_imp ldt_imm tax_imp seb_bac ldy_aba ldt_aba ldx_aba seb_biz
-bcs_rel ldt_idy jmp_zpi bbc_bar ldy_zpx ldt_zpx ldx_zpy bbc_bzr clv_imp ldt_aby tsx_imp clb_bac ldy_abx ldt_abx ldx_aby clb_biz
-cpy_imm cmp_idx nop_imm bbs_bar cpy_zpg cmpt_zpg dec_zpg bbs_bzr iny_imp cmpt_imm dex_imp seb_bac cpy_aba cmpt_aba dec_aba seb_biz
-bne_rel cmp_idy kil_non bbc_bar nop_zpx cmpt_zpx dec_zpx bbc_bzr cld_imp cmpt_aby nop_imp clb_bac nop_abx cmpt_abx dec_abx clb_biz
-cpx_imm sbct_idx nop_imm bbs_bar cpx_zpg sbct_zpg inc_zpg bbs_bzr inx_imp sbc_imm nop_imp seb_bac cpx_aba sbct_aba inc_aba seb_biz
-beq_rel sbct_idy kil_non bbc_bar nop_zpx sbct_zpx inc_zpx bbc_bzr sed_imp sbc_aby nop_imp clb_bac nop_abx sbct_abx inc_abx clb_biz
-reset740
+bcs_m_rel ldt_idy jmp_zpi bbc_bar ldy_m_zpx ldt_zpx ldx_m_zpy bbc_bzr clv_imp ldt_aby tsx_imp clb_bac ldy_m_abx ldt_abx ldx_m_aby clb_biz
+cpy_imm cmp_m_idx wit_imp bbs_bar cpy_zpg cmpt_zpg dec_m_zpg bbs_bzr iny_imp cmpt_imm dex_imp seb_bac cpy_aba cmpt_aba dec_m_aba seb_biz
+bne_m_rel cmp_m_idy kil_non bbc_bar nop_zpx cmpt_zpx dec_m_zpx bbc_bzr cld_imp cmpt_aby nop_imp clb_bac nop_abx cmpt_abx dec_m_abx clb_biz
+cpx_imm sbct_idx nop_imm bbs_bar cpx_zpg sbct_zpg inc_m_zpg bbs_bzr inx_imp sbc_imm nop_imp seb_bac cpx_aba sbct_aba inc_m_aba seb_biz
+beq_m_rel sbct_idy kil_non bbc_bar nop_zpx sbct_zpx inc_m_zpx bbc_bzr sed_imp sbc_m_aby nop_imp clb_bac nop_abx sbct_abx inc_m_abx clb_biz
+reset_m
diff --git a/src/devices/cpu/m6502/dr65c19.lst b/src/devices/cpu/m6502/dr65c19.lst
new file mode 100644
index 00000000000..fcb893d58f9
--- /dev/null
+++ b/src/devices/cpu/m6502/dr65c19.lst
@@ -0,0 +1,20 @@
+# license:BSD-3-Clause
+# copyright-holders:AJR
+# r65c19 - many new instructions, others replaced or subtly altered in behavior
+brk_r_imp ora_zpi mpy_imp tip_imp nop_zpg ora_zpg asl_c_zpg rmb_bzp php_imp ora_imm asl_acc jsb_vec jpi_ind ora_aba asl_c_aba bbr_zpb
+bpl_rel ora_ipx mpa_imp lab_acc nop_zpx ora_zpx asl_c_zpx rmb_bzp clc_imp ora_aby neg_acc jsb_vec nop_c_abx ora_abx asl_c_abx bbr_zpb
+jsr_r_adr and_zpi psh_imp phw_imp bit_zpg and_zpg rol_c_zpg rmb_bzp plp_imp and_imm rol_acc jsb_vec bit_aba and_aba rol_c_aba bbr_zpb
+bmi_rel and_ipx pul_imp plw_imp nop_zpx and_zpx rol_c_zpx rmb_bzp sec_imp and_aby asr_acc jsb_vec nop_c_abx and_abx rol_c_abx bbr_zpb
+rti_imp eor_zpi rnd_imp nop_c_imp nop_zpg eor_zpg lsr_c_zpg rmb_bzp pha_imp eor_imm lsr_acc jsb_vec jmp_adr eor_aba lsr_c_aba bbr_zpb
+bvc_rel eor_ipx clw_imp nop_c_imp nop_zpx eor_zpx lsr_c_zpx rmb_bzp cli_imp eor_aby phy_imp jsb_vec nop_c_abx eor_abx lsr_c_abx bbr_zpb
+rts_r_imp adc_c_zpi taw_imp nop_c_imp add_zpg adc_c_zpg ror_c_zpg rmb_bzp pla_imp adc_c_imm ror_acc jsb_vec jmp_r_ind adc_c_aba ror_c_aba bbr_zpb
+bvs_rel adc_ipx twa_imp nop_c_imp add_zpx adc_c_zpx ror_c_zpx rmb_bzp sei_imp adc_c_aby ply_imp jsb_vec jmp_iax adc_c_abx ror_c_abx bbr_zpb
+bra_rel sta_zpi nop_imm nop_c_imp sty_zpg sta_zpg stx_zpg smb_bzp dey_imp add_imm txa_imp nxt_imp sty_aba sta_aba stx_aba bbs_zpb
+bcc_rel sta_ipx nop_imm nop_c_imp sty_zpx sta_zpx stx_zpy smb_bzp tya_imp sta_aby txs_imp lii_imp nop_c_abx sta_abx nop_c_abx bbs_zpb
+ldy_imm lda_zpi ldx_imm nop_c_imp ldy_zpg lda_zpg ldx_zpg smb_bzp tay_imp lda_imm tax_imp lan_imp ldy_aba lda_aba ldx_aba bbs_zpb
+bcs_rel lda_ipx sti_imz nop_c_imp ldy_zpx lda_zpx ldx_zpy smb_bzp clv_imp lda_aby tsx_imp ini_imp ldy_abx lda_abx ldx_aby bbs_zpb
+cpy_imm cmp_zpi rba_ima nop_c_imp cpy_zpg cmp_zpg dec_c_zpg smb_bzp iny_imp cmp_imm dex_imp phi_imp cpy_aba cmp_aba dec_c_aba bbs_zpb
+bne_rel cmp_ipx sba_ima nop_c_imp exc_zpx cmp_zpx dec_c_zpx smb_bzp cld_imp cmp_aby phx_imp pli_imp nop_c_abx cmp_abx dec_c_abx bbs_zpb
+cpx_imm sbc_c_zpi bar_amr nop_c_imp cpx_zpg sbc_c_zpg inc_c_zpg smb_bzp inx_imp sbc_c_imm nop_imp lai_imp cpx_aba sbc_c_aba inc_c_aba bbs_zpb
+beq_rel sbc_ipx bas_amr nop_c_imp nop_zpx sbc_c_zpx inc_c_zpx smb_bzp sed_imp sbc_c_aby plx_imp pia_imp nop_c_abx sbc_c_abx inc_c_abx bbs_zpb
+reset_r
diff --git a/src/devices/cpu/m6502/dn2a03.lst b/src/devices/cpu/m6502/drp2a03.lst
index 06dcc2610a2..a537c63d589 100644
--- a/src/devices/cpu/m6502/dn2a03.lst
+++ b/src/devices/cpu/m6502/drp2a03.lst
@@ -1,6 +1,6 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
-# n2a03 - D flag is disabled but present in the P register
+# rp2a03 - D flag is disabled but present in the P register
brk_imp ora_idx kil_non slo_idx nop_zpg ora_zpg asl_zpg slo_zpg php_imp ora_imm asl_acc anc_imm nop_aba ora_aba asl_aba slo_aba
bpl_rel ora_idy kil_non slo_idy nop_zpx ora_zpx asl_zpx slo_zpx clc_imp ora_aby nop_imp slo_aby nop_abx ora_abx asl_abx slo_abx
jsr_adr and_idx kil_non rla_idx bit_zpg and_zpg rol_zpg rla_zpg plp_imp and_imm rol_acc anc_imm bit_aba and_aba rol_aba rla_aba
diff --git a/src/devices/cpu/m6502/dm65c02.lst b/src/devices/cpu/m6502/dw65c02.lst
index cb76456593b..d253cfa2774 100644
--- a/src/devices/cpu/m6502/dm65c02.lst
+++ b/src/devices/cpu/m6502/dw65c02.lst
@@ -1,6 +1,6 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
-# m65c02
+# w65c02
brk_c_imp ora_idx nop_imm nop_c_imp tsb_zpg ora_zpg asl_c_zpg nop_c_imp php_imp ora_imm asl_acc nop_c_imp tsb_aba ora_aba asl_c_aba nop_c_imp
bpl_rel ora_idy ora_zpi nop_c_imp trb_zpg ora_zpx asl_c_zpx nop_c_imp clc_imp ora_aby inc_acc nop_c_imp trb_aba ora_abx asl_c_abx nop_c_imp
jsr_adr and_idx nop_imm nop_c_imp bit_zpg and_zpg rol_c_zpg nop_c_imp plp_imp and_imm rol_acc nop_c_imp bit_aba and_aba rol_c_aba nop_c_imp
diff --git a/src/devices/cpu/m6502/dw65c02s.lst b/src/devices/cpu/m6502/dw65c02s.lst
new file mode 100644
index 00000000000..b8d67e3afec
--- /dev/null
+++ b/src/devices/cpu/m6502/dw65c02s.lst
@@ -0,0 +1,20 @@
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# w65c02s - WDC variant, with different dummy fetch patterns for indexed modes
+brk_s_imp ora_s_idx nop_imm nop_c_imp tsb_s_zpg ora_zpg asl_s_zpg rmb_bzp php_imp ora_imm asl_acc nop_c_imp tsb_aba ora_aba asl_c_aba bbr_zpb
+bpl_rel ora_s_idy ora_zpi nop_c_imp trb_s_zpg ora_s_zpx asl_s_zpx rmb_bzp clc_imp ora_s_aby inc_acc nop_c_imp trb_aba ora_s_abx asl_s_abx bbr_zpb
+jsr_adr and_s_idx nop_imm nop_c_imp bit_zpg and_zpg rol_s_zpg rmb_bzp plp_s_imp and_imm rol_acc nop_c_imp bit_aba and_aba rol_c_aba bbr_zpb
+bmi_rel and_s_idy and_zpi nop_c_imp bit_s_zpx and_s_zpx rol_s_zpx rmb_bzp sec_imp and_s_aby dec_acc nop_c_imp bit_s_abx and_s_abx rol_s_abx bbr_zpb
+rti_s_imp eor_s_idx nop_imm nop_c_imp nop_zpg eor_zpg lsr_s_zpg rmb_bzp pha_imp eor_imm lsr_acc nop_c_imp jmp_adr eor_aba lsr_c_aba bbr_zpb
+bvc_rel eor_s_idy eor_zpi nop_c_imp nop_s_zpx eor_s_zpx lsr_s_zpx rmb_bzp cli_imp eor_s_aby phy_imp nop_c_imp nop_c_aba eor_s_abx lsr_s_abx bbr_zpb
+rts_s_imp adc_s_idx nop_imm nop_c_imp stz_zpg adc_c_zpg ror_s_zpg rmb_bzp pla_s_imp adc_c_imm ror_acc nop_c_imp jmp_s_ind adc_c_aba ror_c_aba bbr_zpb
+bvs_rel adc_s_idy adc_c_zpi nop_c_imp stz_s_zpx adc_s_zpx ror_s_zpx rmb_bzp sei_imp adc_s_aby ply_s_imp nop_c_imp jmp_s_iax adc_s_abx ror_s_abx bbr_zpb
+bra_rel sta_s_idx nop_imm nop_c_imp sty_zpg sta_zpg stx_zpg smb_bzp dey_imp bit_imm txa_imp nop_c_imp sty_aba sta_aba stx_aba bbs_zpb
+bcc_rel sta_s_idy sta_zpi nop_c_imp sty_s_zpx sta_s_zpx stx_s_zpy smb_bzp tya_imp sta_s_aby txs_imp nop_c_imp stz_aba sta_s_abx stz_s_abx bbs_zpb
+ldy_imm lda_s_idx ldx_imm nop_c_imp ldy_zpg lda_zpg ldx_zpg smb_bzp tay_imp lda_imm tax_imp nop_c_imp ldy_aba lda_aba ldx_aba bbs_zpb
+bcs_rel lda_s_idy lda_zpi nop_c_imp ldy_s_zpx lda_s_zpx ldx_s_zpy smb_bzp clv_imp lda_s_aby tsx_imp nop_c_imp ldy_s_abx lda_s_abx ldx_s_aby bbs_zpb
+cpy_imm cmp_s_idx nop_imm nop_c_imp cpy_zpg cmp_zpg dec_s_zpg smb_bzp iny_imp cmp_imm dex_imp wai_imp cpy_aba cmp_aba dec_c_aba bbs_zpb
+bne_rel cmp_s_idy cmp_zpi nop_c_imp nop_s_zpx cmp_s_zpx dec_s_zpx smb_bzp cld_imp cmp_s_aby phx_imp stp_imp nop_s_abx cmp_s_abx dec_s_abx bbs_zpb
+cpx_imm sbc_s_idx nop_imm nop_c_imp cpx_zpg sbc_c_zpg inc_s_zpg smb_bzp inx_imp sbc_c_imm nop_imp nop_c_imp cpx_aba sbc_c_aba inc_c_aba bbs_zpb
+beq_rel sbc_s_idy sbc_c_zpi nop_c_imp nop_s_zpx sbc_s_zpx inc_s_zpx smb_bzp sed_imp sbc_s_aby plx_s_imp nop_c_imp nop_s_abx sbc_s_abx inc_s_abx bbs_zpb
+reset_s
diff --git a/src/devices/cpu/m6502/g65sc02.cpp b/src/devices/cpu/m6502/g65sc02.cpp
new file mode 100644
index 00000000000..e9e62cd4880
--- /dev/null
+++ b/src/devices/cpu/m6502/g65sc02.cpp
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ g65sc02.cpp
+
+ 65c02 with internal static registers, making clock stoppable?
+
+ TODO:
+ - none of the CPU type differences are currently emulated (eg. BE pin, ML pin),
+ are any of them meaningful to MAME?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "g65sc02.h"
+
+DEFINE_DEVICE_TYPE(G65SC02, g65sc02_device, "g65sc02", "GTE G65SC02")
+DEFINE_DEVICE_TYPE(G65SC12, g65sc12_device, "g65sc12", "GTE G65SC12")
+DEFINE_DEVICE_TYPE(G65SC102, g65sc102_device, "g65sc102", "GTE G65SC102")
+DEFINE_DEVICE_TYPE(G65SC112, g65sc112_device, "g65sc112", "GTE G65SC112")
+
+g65sc02_device::g65sc02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ w65c02_device(mconfig, type, tag, owner, clock)
+{
+}
+
+g65sc02_device::g65sc02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ g65sc02_device(mconfig, G65SC02, tag, owner, clock)
+{
+}
+
+g65sc12_device::g65sc12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ g65sc02_device(mconfig, G65SC12, tag, owner, clock)
+{
+}
+
+g65sc102_device::g65sc102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ g65sc02_device(mconfig, G65SC102, tag, owner, clock)
+{
+}
+
+g65sc112_device::g65sc112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ g65sc02_device(mconfig, G65SC112, tag, owner, clock)
+{
+}
diff --git a/src/devices/cpu/m6502/g65sc02.h b/src/devices/cpu/m6502/g65sc02.h
new file mode 100644
index 00000000000..e98f068b60d
--- /dev/null
+++ b/src/devices/cpu/m6502/g65sc02.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ g65sc02.h
+
+ 65c02 with internal static registers, making clock stoppable?
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_G65SC02_H
+#define MAME_CPU_M6502_G65SC02_H
+
+#include "w65c02.h"
+
+class g65sc02_device : public w65c02_device {
+public:
+ g65sc02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ g65sc02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class g65sc12_device : public g65sc02_device {
+public:
+ g65sc12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class g65sc102_device : public g65sc02_device {
+public:
+ g65sc102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
+ virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
+};
+
+class g65sc112_device : public g65sc02_device {
+public:
+ g65sc112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+enum {
+ G65SC02_IRQ_LINE = m6502_device::IRQ_LINE,
+ G65SC02_NMI_LINE = m6502_device::NMI_LINE,
+ G65SC02_SET_OVERFLOW = m6502_device::V_LINE
+};
+
+DECLARE_DEVICE_TYPE(G65SC02, g65sc02_device)
+DECLARE_DEVICE_TYPE(G65SC12, g65sc12_device)
+DECLARE_DEVICE_TYPE(G65SC102, g65sc102_device)
+DECLARE_DEVICE_TYPE(G65SC112, g65sc112_device)
+
+#endif // MAME_CPU_M6502_G65SC02_H
diff --git a/src/devices/cpu/m6502/gew12.cpp b/src/devices/cpu/m6502/gew12.cpp
new file mode 100644
index 00000000000..4d77abc7771
--- /dev/null
+++ b/src/devices/cpu/m6502/gew12.cpp
@@ -0,0 +1,229 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/***************************************************************************
+
+ gew7.cpp
+
+ Yamaha GEW2 (65c02-based)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "gew12.h"
+
+#include "m6502mcu.ipp"
+
+#include "bus/generic/slot.h"
+
+
+DEFINE_DEVICE_TYPE(GEW12, gew12_device, "gew12", "Yamaha YMW728-F (GEW12)")
+
+gew12_device::gew12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : m6502_mcu_device_base<w65c02_device>(mconfig, GEW12, tag, owner, clock)
+ , device_mixer_interface(mconfig, *this)
+ , m_in_cb(*this, 0xff), m_out_cb(*this)
+ , m_rom(*this, DEVICE_SELF)
+ , m_bank(*this, "bank%u", 0U)
+{
+ program_config.m_internal_map = address_map_constructor(FUNC(gew12_device::internal_map), this);
+}
+
+
+void gew12_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: PCM, UART
+}
+
+void gew12_device::device_start()
+{
+ w65c02_device::device_start();
+
+ m_bank_mask = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(m_rom->bytes() >> 14),
+ [this, base = &m_rom->as_u8()] (unsigned entry, unsigned page)
+ {
+ m_bank[0]->configure_entry(entry, &base[page << 14]);
+ m_bank[1]->configure_entry(entry, &base[page << 14]);
+ });
+
+ m_timer_base[0] = m_timer_base[1] = 0;
+
+ std::fill(std::begin(m_port_data), std::end(m_port_data), 0);
+ std::fill(std::begin(m_port_ddr), std::end(m_port_ddr), 0);
+
+ save_item(NAME(m_irq_pending));
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_timer_count));
+ save_item(NAME(m_timer_base));
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_ddr));
+}
+
+void gew12_device::device_reset()
+{
+ m6502_mcu_device_base<w65c02_device>::device_reset();
+
+ internal_update();
+ m_irq_pending = 0;
+ m_irq_enable = 0;
+
+ m_timer_count[0] = m_timer_count[1] = 0;
+ internal_update();
+}
+
+
+void gew12_device::internal_map(address_map &map)
+{
+ map(0x0000, 0x07ff).ram();
+
+ // TODO: sound registers
+ map(0x1000, 0x103f).ram();
+
+ map(0x1f00, 0x1f00).rw(FUNC(gew12_device::irq_stat_r), FUNC(gew12_device::irq_en_w));
+ map(0x1f01, 0x1f01).w(FUNC(gew12_device::timer_stat_w));
+
+ // TODO: UART
+ // map(0x1f11, 0x1f11) Rx data
+ // map(0x1f12, 0x1f12) status (bits 0-1: error, bit 2: Rx ready, bit 3: Tx ready)
+ // map(0x1f13, 0x1f13) Tx data
+
+ map(0x1f20, 0x1f23).w(FUNC(gew12_device::timer_count_w));
+ map(0x1f24, 0x1f25).r(FUNC(gew12_device::timer_count_r));
+
+ // TODO - only the last port (PL) is known for sure
+ // on psr160/260, the rest seem to all be handled by built-in key/button scanning
+ map(0x1f2a, 0x1f2f).rw(FUNC(gew12_device::port_r), FUNC(gew12_device::port_w));
+ map(0x1f3a, 0x1f3f).rw(FUNC(gew12_device::port_ddr_r), FUNC(gew12_device::port_ddr_w));
+
+ map(0x1f52, 0x1f52).lw8(NAME([this](uint8_t data) { m_bank[0]->set_entry(data & m_bank_mask); }));
+ map(0x1f53, 0x1f53).nopw(); // bank 0 MSB? (always zero)
+ map(0x1f54, 0x1f54).lw8(NAME([this](uint8_t data) { m_bank[1]->set_entry(data & m_bank_mask); }));
+ map(0x1f55, 0x1f55).nopw(); // bank 1 MSB? (always zero)
+
+ map(0x4000, 0x7fff).bankr(m_bank[0]);
+ map(0x8000, 0xbfff).bankr(m_bank[1]);
+ map(0xc000, 0xffff).rom().region(DEVICE_SELF, 0);
+}
+
+
+void gew12_device::internal_update(u64 current_time)
+{
+ u64 event_time(0U);
+ add_event(event_time, timer_update(0, current_time));
+ add_event(event_time, timer_update(1, current_time));
+ recompute_bcount(event_time);
+}
+
+
+u8 gew12_device::irq_stat_r()
+{
+ internal_update();
+ return m_irq_pending & m_irq_enable;
+}
+
+void gew12_device::irq_en_w(u8 data)
+{
+ internal_update();
+ m_irq_enable = data;
+ irq_update();
+ internal_update();
+}
+
+void gew12_device::internal_irq(int num, int state)
+{
+ if (state == ASSERT_LINE)
+ m_irq_pending |= (1 << num);
+ else
+ m_irq_pending &= ~(1 << num);
+
+ irq_update();
+}
+
+void gew12_device::irq_update()
+{
+ if (m_irq_pending & m_irq_enable)
+ set_input_line(W65C02_IRQ_LINE, ASSERT_LINE);
+ else
+ set_input_line(W65C02_IRQ_LINE, CLEAR_LINE);
+}
+
+
+void gew12_device::timer_stat_w(u8 data)
+{
+ internal_update();
+ if (BIT(data, 0))
+ internal_irq(INTERNAL_IRQ_TIMER0, CLEAR_LINE);
+ if (BIT(data, 1))
+ internal_irq(INTERNAL_IRQ_TIMER1, CLEAR_LINE);
+ internal_update();
+}
+
+u8 gew12_device::timer_count_r(offs_t offset)
+{
+ // both timer IRQ handlers read the current count from the same registers
+ // apparently reading timer 1 count if its IRQ is pending, else timer 0 count
+ internal_update();
+ const unsigned timer = BIT(m_irq_pending, INTERNAL_IRQ_TIMER1);
+
+ if (!BIT(offset, 0))
+ return m_timer_count[timer];
+ else
+ return m_timer_count[timer] >> 8;
+}
+
+void gew12_device::timer_count_w(offs_t offset, u8 data)
+{
+ const unsigned timer = offset >> 1;
+
+ internal_update();
+ if (!BIT(offset, 0))
+ m_timer_count[timer] = (m_timer_count[timer] & 0xff00) | data;
+ else
+ m_timer_count[timer] = (m_timer_count[timer] & 0x00ff) | (data << 8);
+ internal_update();
+}
+
+u64 gew12_device::timer_update(int num, u64 current_time)
+{
+ static constexpr unsigned tick_rate = 48;
+
+ const u64 ticks = current_time / tick_rate;
+ const u64 elapsed = ticks - m_timer_base[num];
+ m_timer_base[num] = ticks;
+
+ // TODO: how are the timers enabled/disabled?
+ // for now, just have 'timer IRQ enable' double as 'timer enable'
+ if (!BIT(m_irq_enable, INTERNAL_IRQ_TIMER0 + num))
+ return 0;
+
+ if (elapsed > m_timer_count[num])
+ internal_irq(INTERNAL_IRQ_TIMER0 + num, ASSERT_LINE);
+
+ m_timer_count[num] -= elapsed;
+
+ return (m_timer_base[num] + m_timer_count[num] + 1) * tick_rate;
+}
+
+
+u8 gew12_device::port_r(offs_t offset)
+{
+ const u8 out_data = m_port_data[offset] & ~m_port_ddr[offset];
+ return out_data | (m_in_cb[offset]() & m_port_ddr[offset]);
+}
+
+void gew12_device::port_w(offs_t offset, u8 data)
+{
+ m_port_data[offset] = data;
+ m_out_cb[offset](0, m_port_data[offset], ~m_port_ddr[offset]);
+}
+
+u8 gew12_device::port_ddr_r(offs_t offset)
+{
+ return m_port_ddr[offset];
+}
+
+void gew12_device::port_ddr_w(offs_t offset, u8 data)
+{
+ m_port_ddr[offset] = data;
+ m_out_cb[offset](0, m_port_data[offset], ~m_port_ddr[offset]);
+}
diff --git a/src/devices/cpu/m6502/gew12.h b/src/devices/cpu/m6502/gew12.h
new file mode 100644
index 00000000000..101116c6903
--- /dev/null
+++ b/src/devices/cpu/m6502/gew12.h
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/***************************************************************************
+
+ gew12.h
+
+ Yamaha GEW12 (65c02-based)
+
+***************************************************************************/
+#ifndef MAME_CPU_M6502_GEW12_H
+#define MAME_CPU_M6502_GEW12_H
+
+#include "m6502mcu.h"
+#include "w65c02.h"
+
+class gew12_device : public m6502_mcu_device_base<w65c02_device>, public device_mixer_interface {
+public:
+ gew12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<offs_t Num> auto port_in_cb() { return m_in_cb[Num].bind(); }
+ template<offs_t Num> auto port_out_cb() { return m_out_cb[Num].bind(); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void internal_update(u64 current_time) override;
+ using m6502_mcu_device_base<w65c02_device>::internal_update;
+
+ enum
+ {
+ INTERNAL_IRQ_TIMER0,
+ INTERNAL_IRQ_TIMER1,
+ INTERNAL_IRQ_MIDI_TX,
+ INTERNAL_IRQ_MIDI_RX
+ };
+
+ u8 irq_stat_r();
+ void irq_en_w(u8 data);
+ void timer_stat_w(u8 data);
+
+ u8 timer_count_r(offs_t offset);
+ void timer_count_w(offs_t offset, u8 data);
+ u64 timer_update(int num, u64 current_time);
+
+ u8 port_r(offs_t offset);
+ void port_w(offs_t offset, u8 data);
+ u8 port_ddr_r(offs_t offset);
+ void port_ddr_w(offs_t offset, u8 data);
+
+ template<int Num>
+ void internal_irq(int state) { internal_irq(Num, state); }
+ void internal_irq(int num, int state);
+
+ void irq_update();
+
+ void internal_map(address_map &map) ATTR_COLD;
+
+ u8 m_irq_pending, m_irq_enable;
+
+ u16 m_timer_count[2];
+ u64 m_timer_base[2];
+
+ devcb_read8::array<6> m_in_cb;
+ devcb_write8::array<6> m_out_cb;
+ u8 m_port_data[6];
+ u8 m_port_ddr[6];
+
+ required_memory_region m_rom;
+ required_memory_bank_array<2> m_bank;
+ u8 m_bank_mask;
+};
+
+DECLARE_DEVICE_TYPE(GEW12, gew12_device)
+
+#endif // MAME_CPU_M6502_GEW12_H
diff --git a/src/devices/cpu/m6502/gew7.cpp b/src/devices/cpu/m6502/gew7.cpp
new file mode 100644
index 00000000000..76e1378d9e8
--- /dev/null
+++ b/src/devices/cpu/m6502/gew7.cpp
@@ -0,0 +1,216 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/***************************************************************************
+
+ gew7.cpp
+
+ Yamaha GEW7, GEW7I, GEW7S (65c02-based)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "gew7.h"
+
+#include "m6502mcu.ipp"
+
+#include "bus/generic/slot.h"
+
+
+DEFINE_DEVICE_TYPE(GEW7, gew7_device, "gew7", "Yamaha YMW270-F (GEW7)")
+
+gew7_device::gew7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : m6502_mcu_device_base<w65c02_device>(mconfig, GEW7, tag, owner, clock)
+ , device_mixer_interface(mconfig, *this)
+ , m_in_cb(*this, 0xff), m_out_cb(*this)
+ , m_rom(*this, DEVICE_SELF)
+ , m_bank(*this, "bank%u", 0U)
+ , m_pcm(*this, "pcm")
+{
+ program_config.m_internal_map = address_map_constructor(FUNC(gew7_device::internal_map), this);
+
+ std::fill(std::begin(m_port_force_bits), std::end(m_port_force_bits), 0);
+ std::fill(std::begin(m_port_force_mask), std::end(m_port_force_mask), 0);
+}
+
+
+void gew7_device::device_add_mconfig(machine_config &config)
+{
+ GEW7_PCM(config, m_pcm, DERIVED_CLOCK(1, 1));
+ m_pcm->set_device_rom_tag(m_rom);
+ m_pcm->add_route(0, *this, 1.0, 0);
+ m_pcm->add_route(1, *this, 1.0, 1);
+}
+
+void gew7_device::device_start()
+{
+ m6502_mcu_device_base<w65c02_device>::device_start();
+
+ m_bank_mask = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(m_rom->bytes() >> 14),
+ [this, base = &m_rom->as_u8()] (unsigned entry, unsigned page)
+ {
+ m_bank[0]->configure_entry(entry, &base[page << 14]);
+ m_bank[1]->configure_entry(entry, &base[page << 14]);
+ });
+
+ m_timer_base[0] = m_timer_base[1] = 0;
+
+ std::fill(std::begin(m_port_data), std::end(m_port_data), 0);
+ std::fill(std::begin(m_port_ddr), std::end(m_port_ddr), 0);
+
+ save_item(NAME(m_timer_stat));
+ save_item(NAME(m_timer_en));
+ save_item(NAME(m_timer_count));
+ save_item(NAME(m_timer_base));
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_ddr));
+}
+
+void gew7_device::device_reset()
+{
+ m6502_mcu_device_base<w65c02_device>::device_reset();
+
+ internal_update();
+ m_timer_stat = m_timer_en = 0;
+ m_timer_count[0] = m_timer_count[1] = 0;
+ internal_update();
+}
+
+
+void gew7_device::internal_map(address_map &map)
+{
+ map(0x0000, 0x005f).rw(m_pcm, FUNC(gew7_pcm_device::read), FUNC(gew7_pcm_device::write));
+ map(0x0060, 0x00ff).mirror(0x0100).ram();
+ map(0x0200, 0x022f).rw(m_pcm, FUNC(gew7_pcm_device::read_hi), FUNC(gew7_pcm_device::write_hi));
+ map(0x0230, 0x023f).ram();
+
+ map(0x0400, 0x0400).rw(FUNC(gew7_device::timer_stat_r), FUNC(gew7_device::timer_stat_w));
+ map(0x0401, 0x0401).w(FUNC(gew7_device::timer_en_w));
+ map(0x0402, 0x0405).rw(FUNC(gew7_device::timer_count_r), FUNC(gew7_device::timer_count_w));
+ map(0x0408, 0x0409).w(FUNC(gew7_device::bank_w));
+ map(0x040a, 0x040f).rw(FUNC(gew7_device::port_r), FUNC(gew7_device::port_w));
+ map(0x0410, 0x0415).rw(FUNC(gew7_device::port_ddr_r), FUNC(gew7_device::port_ddr_w));
+
+ map(0x4000, 0x7fff).bankr(m_bank[0]);
+ map(0x8000, 0xbfff).bankr(m_bank[1]);
+ map(0xc000, 0xffff).rom().region(DEVICE_SELF, 0);
+}
+
+
+void gew7_device::internal_update(u64 current_time)
+{
+ u64 event_time(0U);
+ add_event(event_time, timer_update(0, current_time));
+ add_event(event_time, timer_update(1, current_time));
+ recompute_bcount(event_time);
+}
+
+u8 gew7_device::timer_stat_r()
+{
+ internal_update();
+ return m_timer_stat;
+}
+
+void gew7_device::timer_stat_w(u8 data)
+{
+ internal_update();
+ m_timer_stat &= ~data;
+
+ if (!(m_timer_stat & 3))
+ set_input_line(W65C02_IRQ_LINE, CLEAR_LINE);
+ internal_update();
+}
+
+void gew7_device::timer_en_w(u8 data)
+{
+ internal_update();
+ m_timer_en = data;
+ internal_update();
+}
+
+u8 gew7_device::timer_count_r(offs_t offset)
+{
+ const unsigned timer = offset >> 1;
+
+ internal_update();
+ if (!BIT(offset, 0))
+ return m_timer_count[timer];
+ else
+ return m_timer_count[timer] >> 8;
+}
+
+void gew7_device::timer_count_w(offs_t offset, u8 data)
+{
+ const unsigned timer = offset >> 1;
+
+ internal_update();
+ if (!BIT(offset, 0))
+ m_timer_count[timer] = (m_timer_count[timer] & 0xff00) | data;
+ else
+ m_timer_count[timer] = (m_timer_count[timer] & 0x00ff) | (data << 8);
+ internal_update();
+}
+
+u64 gew7_device::timer_update(int num, u64 current_time)
+{
+ static constexpr unsigned tick_rate = 48;
+
+ const u64 ticks = current_time / tick_rate;
+ const u64 elapsed = ticks - m_timer_base[num];
+ m_timer_base[num] = ticks;
+
+ if (!BIT(m_timer_en, num))
+ return 0; // timer disabled
+
+ if (elapsed > m_timer_count[num])
+ {
+ m_timer_stat |= (1 << num);
+ set_input_line(W65C02_IRQ_LINE, ASSERT_LINE);
+ }
+
+ m_timer_count[num] -= elapsed;
+
+ return (m_timer_base[num] + m_timer_count[num] + 1) * tick_rate;
+}
+
+
+void gew7_device::bank_w(offs_t offset, u8 data)
+{
+ m_bank[offset]->set_entry(data & m_bank_mask);
+}
+
+
+void gew7_device::port_force_bits(offs_t num, u8 bits, u8 mask)
+{
+ // Evidently (at least on the original YMW270F), tying a port pin to +5V or ground is expected
+ // to affect the value read from the port even when the pin is configured as output.
+ // PSS-11, PSS-21, PSS-31, and PSR-75 (which all use the same ROM) all rely on this in order to
+ // correctly detect what model they are.
+ m_port_force_bits[num] = bits;
+ m_port_force_mask[num] = mask;
+}
+
+u8 gew7_device::port_r(offs_t offset)
+{
+ const u8 out_data = m_port_data[offset] & m_port_ddr[offset];
+ const u8 in_data = m_in_cb[offset]() & ~m_port_ddr[offset];
+
+ return ((out_data | in_data) & ~m_port_force_mask[offset]) | m_port_force_bits[offset];
+}
+
+void gew7_device::port_w(offs_t offset, u8 data)
+{
+ m_port_data[offset] = data;
+ m_out_cb[offset](0, m_port_data[offset], m_port_ddr[offset]);
+}
+
+u8 gew7_device::port_ddr_r(offs_t offset)
+{
+ return m_port_ddr[offset];
+}
+
+void gew7_device::port_ddr_w(offs_t offset, u8 data)
+{
+ m_port_ddr[offset] = data;
+ m_out_cb[offset](0, m_port_data[offset], m_port_ddr[offset]);
+}
diff --git a/src/devices/cpu/m6502/gew7.h b/src/devices/cpu/m6502/gew7.h
new file mode 100644
index 00000000000..5c9a891559e
--- /dev/null
+++ b/src/devices/cpu/m6502/gew7.h
@@ -0,0 +1,74 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/***************************************************************************
+
+ gew7.h
+
+ Yamaha GEW7, GEW7I, GEW7S (65c02-based)
+
+***************************************************************************/
+#ifndef MAME_CPU_M6502_GEW7_H
+#define MAME_CPU_M6502_GEW7_H
+
+#include "m6502mcu.h"
+#include "w65c02.h"
+#include "sound/gew7.h"
+
+class gew7_device : public m6502_mcu_device_base<w65c02_device>, public device_mixer_interface
+{
+public:
+ gew7_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+ template<offs_t Num> auto port_in_cb() { return m_in_cb[Num].bind(); }
+ template<offs_t Num> auto port_out_cb() { return m_out_cb[Num].bind(); }
+
+ void port_force_bits(offs_t num, u8 bits, u8 mask);
+
+protected:
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void internal_update(u64 current_time) override;
+ using m6502_mcu_device_base<w65c02_device>::internal_update;
+
+ u8 timer_stat_r();
+ void timer_stat_w(u8 data);
+ void timer_en_w(u8 data);
+
+ u8 timer_count_r(offs_t offset);
+ void timer_count_w(offs_t offset, u8 data);
+ u64 timer_update(int num, u64 current_time);
+
+ void bank_w(offs_t offset, u8 data);
+
+ u8 port_r(offs_t offset);
+ void port_w(offs_t offset, u8 data);
+ u8 port_ddr_r(offs_t offset);
+ void port_ddr_w(offs_t offset, u8 data);
+
+ void internal_map(address_map &map) ATTR_COLD;
+
+ u8 m_timer_stat, m_timer_en;
+ u16 m_timer_count[2];
+ u64 m_timer_base[2];
+
+ devcb_read8::array<6> m_in_cb;
+ devcb_write8::array<6> m_out_cb;
+ u8 m_port_data[6];
+ u8 m_port_ddr[6];
+ u8 m_port_force_bits[6];
+ u8 m_port_force_mask[6];
+
+ required_memory_region m_rom;
+ required_memory_bank_array<2> m_bank;
+ u8 m_bank_mask;
+
+ required_device<gew7_pcm_device> m_pcm;
+};
+
+DECLARE_DEVICE_TYPE(GEW7, gew7_device)
+
+#endif // MAME_CPU_M6502_GEW7_H
diff --git a/src/devices/cpu/m6502/m3745x.cpp b/src/devices/cpu/m6502/m3745x.cpp
index df65754bd78..a8552e51d4b 100644
--- a/src/devices/cpu/m6502/m3745x.cpp
+++ b/src/devices/cpu/m6502/m3745x.cpp
@@ -40,9 +40,9 @@ DEFINE_DEVICE_TYPE(M37450, m37450_device, "m37450", "Mitsubishi M37450")
m3745x_device::m3745x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map) :
m740_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map),
- m_read_p{{*this}, {*this}, {*this}, {*this}},
- m_write_p{{*this}, {*this}, {*this}, {*this}},
- m_read_ad{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}},
+ m_read_p(*this, 0),
+ m_write_p(*this),
+ m_read_ad(*this, 0),
m_intreq1(0),
m_intreq2(0),
m_intctrl1(0),
@@ -58,20 +58,11 @@ m3745x_device::m3745x_device(const machine_config &mconfig, device_type type, co
void m3745x_device::device_start()
{
- for (int i = 0; i < 4; i++)
+ for (int i = TIMER_1; i <= TIMER_3; i++)
{
- m_read_p[i].resolve_safe(0);
- m_write_p[i].resolve_safe();
- }
- for (int i = 0; i < 8; i++)
- {
- m_read_ad[i].resolve_safe(0);
- }
-
- for (int i = 0; i < NUM_TIMERS; i++)
- {
- m_timers[i] = timer_alloc(i, nullptr);
+ m_timers[i] = machine().scheduler().timer_alloc(timer_expired_delegate());
}
+ m_timers[TIMER_ADC] = timer_alloc(FUNC(m3745x_device::adc_complete), this);
m740_device::device_start();
@@ -122,22 +113,13 @@ void m3745x_device::device_reset()
m_last_all_ints = 0;
}
-void m3745x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(m3745x_device::adc_complete)
{
- switch (id)
- {
- case TIMER_ADC:
- m_timers[TIMER_ADC]->adjust(attotime::never);
-
- m_adctrl |= ADCTRL_COMPLETE;
- m_intreq2 |= IRQ2_ADC;
- recalc_irqs();
- break;
+ m_timers[TIMER_ADC]->adjust(attotime::never);
- default:
- printf("M3775x: unknown timer expire %d\n", id);
- break;
- }
+ m_adctrl |= ADCTRL_COMPLETE;
+ m_intreq2 |= IRQ2_ADC;
+ recalc_irqs();
}
void m3745x_device::execute_set_input(int inputnum, int state)
@@ -176,10 +158,6 @@ void m3745x_device::execute_set_input(int inputnum, int state)
m_intreq1 &= ~IRQ1_INT3;
}
break;
-
- case M3745X_SET_OVERFLOW: // the base 740 class can handle this
- m740_device::execute_set_input(M740_SET_OVERFLOW, state);
- break;
}
recalc_irqs();
@@ -249,7 +227,7 @@ uint8_t m3745x_device::read_port(uint8_t offset)
return incoming;
}
-READ8_MEMBER(m3745x_device::ports_r)
+uint8_t m3745x_device::ports_r(offs_t offset)
{
switch (offset)
{
@@ -278,7 +256,7 @@ READ8_MEMBER(m3745x_device::ports_r)
return 0xff;
}
-WRITE8_MEMBER(m3745x_device::ports_w)
+void m3745x_device::ports_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -319,7 +297,7 @@ WRITE8_MEMBER(m3745x_device::ports_w)
}
}
-READ8_MEMBER(m3745x_device::intregs_r)
+uint8_t m3745x_device::intregs_r(offs_t offset)
{
switch (offset)
{
@@ -341,7 +319,7 @@ READ8_MEMBER(m3745x_device::intregs_r)
return 0;
}
-WRITE8_MEMBER(m3745x_device::intregs_w)
+void m3745x_device::intregs_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -365,7 +343,7 @@ WRITE8_MEMBER(m3745x_device::intregs_w)
recalc_irqs();
}
-READ8_MEMBER(m3745x_device::adc_r)
+uint8_t m3745x_device::adc_r(offs_t offset)
{
switch (offset)
{
@@ -381,7 +359,7 @@ READ8_MEMBER(m3745x_device::adc_r)
return 0;
}
-WRITE8_MEMBER(m3745x_device::adc_w)
+void m3745x_device::adc_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -395,8 +373,7 @@ WRITE8_MEMBER(m3745x_device::adc_w)
// starting a conversion? this takes 50 cycles.
if (!(m_adctrl & ADCTRL_COMPLETE))
{
- double hz = (double)clock() / 50.0;
- m_timers[TIMER_ADC]->adjust(attotime::from_hz(hz));
+ m_timers[TIMER_ADC]->adjust(cycles_to_attotime(50));
}
break;
}
diff --git a/src/devices/cpu/m6502/m3745x.h b/src/devices/cpu/m6502/m3745x.h
index b499019036b..9f7bc5acc93 100644
--- a/src/devices/cpu/m6502/m3745x.h
+++ b/src/devices/cpu/m6502/m3745x.h
@@ -33,9 +33,7 @@ public:
{
M3745X_INT1_LINE = INPUT_LINE_IRQ0,
M3745X_INT2_LINE,
- M3745X_INT3_LINE,
-
- M3745X_SET_OVERFLOW = M740_SET_OVERFLOW
+ M3745X_INT3_LINE
};
const address_space_config m_program_config;
@@ -44,16 +42,12 @@ public:
template<std::size_t Bit> auto write_p() { return m_write_p[Bit-3].bind(); }
template<std::size_t Bit> auto read_ad() { return m_read_ad[Bit].bind(); }
- devcb_read8 m_read_p[4];
- devcb_write8 m_write_p[4];
- devcb_read8 m_read_ad[8];
-
- DECLARE_READ8_MEMBER(ports_r);
- DECLARE_WRITE8_MEMBER(ports_w);
- DECLARE_READ8_MEMBER(adc_r);
- DECLARE_WRITE8_MEMBER(adc_w);
- DECLARE_READ8_MEMBER(intregs_r);
- DECLARE_WRITE8_MEMBER(intregs_w);
+ uint8_t ports_r(offs_t offset);
+ void ports_w(offs_t offset, uint8_t data);
+ uint8_t adc_r(offs_t offset);
+ void adc_w(offs_t offset, uint8_t data);
+ uint8_t intregs_r(offs_t offset);
+ void intregs_w(offs_t offset, uint8_t data);
bool are_port_bits_output(uint8_t port, uint8_t mask) { return ((m_ddrs[port] & mask) == mask) ? true : false; }
@@ -62,17 +56,26 @@ protected:
m3745x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void execute_set_input(int inputnum, int state) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual space_config_vector memory_space_config() const override;
+ // device_execute_interface overrides
+ virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
+ virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ TIMER_CALLBACK_MEMBER(adc_complete);
+
void send_port(uint8_t offset, uint8_t data);
uint8_t read_port(uint8_t offset);
void recalc_irqs();
+ devcb_read8::array<4> m_read_p;
+ devcb_write8::array<4> m_write_p;
+ devcb_read8::array<8> m_read_ad;
+
uint8_t m_ports[6], m_ddrs[6];
uint8_t m_intreq1, m_intreq2, m_intctrl1, m_intctrl2;
uint8_t m_adctrl;
@@ -87,7 +90,7 @@ class m37450_device : public m3745x_device
public:
m37450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void m37450_map(address_map &map);
+ void m37450_map(address_map &map) ATTR_COLD;
protected:
m37450_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
};
diff --git a/src/devices/cpu/m6502/m37640.cpp b/src/devices/cpu/m6502/m37640.cpp
new file mode 100644
index 00000000000..7341e283178
--- /dev/null
+++ b/src/devices/cpu/m6502/m37640.cpp
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Mitsubishi M37640 8-bit microcontroller with usb support
+
+#include "emu.h"
+#include "m37640.h"
+
+DEFINE_DEVICE_TYPE(M37640, m37640_device, "m37640", "Mitsubishi M37640")
+
+m37640_device::m37640_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 mode) :
+ m740_device(mconfig, M37640, tag, owner, clock),
+ m_mode(mode)
+{
+ program_config.m_internal_map = address_map_constructor(FUNC(m37640_device::map), this);
+}
+
+void m37640_device::device_start()
+{
+ m740_device::device_start();
+}
+
+void m37640_device::device_reset()
+{
+ m740_device::device_start();
+}
+
+void m37640_device::map(address_map &map)
+{
+ (void)m_mode;
+}
diff --git a/src/devices/cpu/m6502/m37640.h b/src/devices/cpu/m6502/m37640.h
new file mode 100644
index 00000000000..efd7077a426
--- /dev/null
+++ b/src/devices/cpu/m6502/m37640.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+#ifndef MAME_CPU_M6502_M37640_H
+#define MAME_CPU_M6502_M37640_H
+
+#pragma once
+
+#include "m740.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> m37640_device
+
+class m37640_device : public m740_device
+{
+public:
+ enum {
+ INT1_LINE = INPUT_LINE_IRQ0,
+ INT2_LINE,
+ };
+
+ m37640_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 mode = 2);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u32 m_mode;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(M37640, m37640_device)
+
+#endif // MAME_CPU_M6502_M37640_H
diff --git a/src/devices/cpu/m6502/m4510.cpp b/src/devices/cpu/m6502/m4510.cpp
index 9e67462e4d0..4e6f97b56e4 100644
--- a/src/devices/cpu/m6502/m4510.cpp
+++ b/src/devices/cpu/m6502/m4510.cpp
@@ -15,12 +15,15 @@
#include "m4510.h"
#include "m4510d.h"
-DEFINE_DEVICE_TYPE(M4510, m4510_device, "m4510", "CSG M4510")
+DEFINE_DEVICE_TYPE(M4510, m4510_device, "m4510", "CSG 4510")
m4510_device::m4510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m65ce02_device(mconfig, M4510, tag, owner, clock),
map_enable(0),
- nomap(false)
+ nomap(false),
+ read_port(*this, 0),
+ write_port(*this),
+ dir(0), port(0), drive(0)
{
program_config.m_addr_width = 20;
program_config.m_logaddr_width = 16;
@@ -28,6 +31,14 @@ m4510_device::m4510_device(const machine_config &mconfig, const char *tag, devic
sprogram_config.m_addr_width = 20;
sprogram_config.m_logaddr_width = 16;
sprogram_config.m_page_shift = 13;
+ pullup = 0x00;
+ floating = 0x00;
+}
+
+void m4510_device::set_pulls(uint8_t _pullup, uint8_t _floating)
+{
+ pullup = _pullup;
+ floating = _floating;
}
std::unique_ptr<util::disasm_interface> m4510_device::create_disassembler()
@@ -35,14 +46,21 @@ std::unique_ptr<util::disasm_interface> m4510_device::create_disassembler()
return std::make_unique<m4510_disassembler>();
}
+void m4510_device::init_port()
+{
+ save_item(NAME(pullup));
+ save_item(NAME(floating));
+ save_item(NAME(dir));
+ save_item(NAME(port));
+ save_item(NAME(drive));
+}
+
void m4510_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_4510_nd>(this);
- else
- mintf = std::make_unique<mi_4510_normal>(this);
+ mintf = std::make_unique<mi_4510>(this);
m65ce02_device::init();
+ init_port();
save_item(NAME(map_offset));
save_item(NAME(map_enable));
@@ -54,59 +72,99 @@ void m4510_device::device_reset()
map_enable = 0;
nomap = true;
- // Wild guess, this setting makes the cpu start executing some code in the c65 driver
- //map_offset[1] = 0x2e000;
- //map_enable = 0x80;
m65ce02_device::device_reset();
+ dir = 0xff;
+ port = 0xff;
+ drive = 0xff;
+ update_port();
}
-bool m4510_device::memory_translate(int spacenum, int intention, offs_t &address)
+void m4510_device::update_port()
{
- if (spacenum == AS_PROGRAM)
- {
- address = map(address);
- }
+ drive = (port & dir) | (drive & ~dir);
+ write_port((port & dir) | (pullup & ~dir));
+}
- return true;
+uint8_t m4510_device::get_port()
+{
+ return (port & dir) | (pullup & ~dir);
}
-m4510_device::mi_4510_normal::mi_4510_normal(m4510_device *_base)
+uint8_t m4510_device::dir_r()
{
- base = _base;
+ return dir;
}
-uint8_t m4510_device::mi_4510_normal::read(uint16_t adr)
+uint8_t m4510_device::port_r()
{
- return program->read_byte(base->map(adr));
+ return ((read_port() | (floating & drive)) & ~dir) | (port & dir);
}
-uint8_t m4510_device::mi_4510_normal::read_sync(uint16_t adr)
+void m4510_device::dir_w(uint8_t data)
{
- return scache->read_byte(base->map(adr));
+ dir = data;
+ update_port();
}
-uint8_t m4510_device::mi_4510_normal::read_arg(uint16_t adr)
+void m4510_device::port_w(uint8_t data)
{
- return cache->read_byte(base->map(adr));
+ port = data;
+ update_port();
+}
+
+bool m4510_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space)
+{
+ target_space = &space(spacenum);
+ if (spacenum == AS_PROGRAM)
+ {
+ address = map(address);
+ }
+
+ return true;
+}
+
+m4510_device::mi_4510::mi_4510(m4510_device *_base)
+{
+ base = _base;
}
-void m4510_device::mi_4510_normal::write(uint16_t adr, uint8_t val)
+uint8_t m4510_device::mi_4510::read(uint16_t adr)
{
- program->write_byte(base->map(adr), val);
+ uint8_t res = program.read_byte(base->map(adr));
+ if(adr == 0x0000)
+ res = base->dir_r();
+ else if(adr == 0x0001)
+ res = base->port_r();
+ return res;
}
-m4510_device::mi_4510_nd::mi_4510_nd(m4510_device *_base) : mi_4510_normal(_base)
+uint8_t m4510_device::mi_4510::read_sync(uint16_t adr)
{
+ uint8_t res = csprogram.read_byte(base->map(adr));
+ if(adr == 0x0000)
+ res = base->dir_r();
+ else if(adr == 0x0001)
+ res = base->port_r();
+ return res;
}
-uint8_t m4510_device::mi_4510_nd::read_sync(uint16_t adr)
+uint8_t m4510_device::mi_4510::read_arg(uint16_t adr)
{
- return sprogram->read_byte(base->map(adr));
+ uint8_t res = cprogram.read_byte(base->map(adr));
+ if(adr == 0x0000)
+ res = base->dir_r();
+ else if(adr == 0x0001)
+ res = base->port_r();
+ return res;
}
-uint8_t m4510_device::mi_4510_nd::read_arg(uint16_t adr)
+void m4510_device::mi_4510::write(uint16_t adr, uint8_t val)
{
- return program->read_byte(base->map(adr));
+ program.write_byte(base->map(adr), val);
+ if(adr == 0x0000)
+ base->dir_w(val);
+ else if(adr == 0x0001)
+ base->port_w(val);
}
#include "cpu/m6502/m4510.hxx"
diff --git a/src/devices/cpu/m6502/m4510.h b/src/devices/cpu/m6502/m4510.h
index 2db5ea3fde3..c0e21977c2b 100644
--- a/src/devices/cpu/m6502/m4510.h
+++ b/src/devices/cpu/m6502/m4510.h
@@ -4,7 +4,7 @@
m4510.h
- 65ce02 with a mmu and a port
+ 65ce02 with a mmu and a cia integrated
***************************************************************************/
@@ -26,34 +26,37 @@ public:
bool get_nomap() const { return nomap; }
+ uint8_t get_port();
+ void set_pulls(uint8_t pullup, uint8_t pulldown);
+
+ auto read_callback() { return read_port.bind(); }
+ auto write_callback() { return write_port.bind(); }
+
protected:
uint32_t map_offset[2];
uint8_t map_enable;
bool nomap;
- class mi_4510_normal : public memory_interface {
+ class mi_4510 : public memory_interface {
public:
m4510_device *base;
- mi_4510_normal(m4510_device *base);
- virtual ~mi_4510_normal() {}
+ mi_4510(m4510_device *base);
+ virtual ~mi_4510() {}
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
virtual uint8_t read_arg(uint16_t adr) override;
virtual void write(uint16_t adr, uint8_t val) override;
};
- class mi_4510_nd : public mi_4510_normal {
- public:
- mi_4510_nd(m4510_device *base);
- virtual ~mi_4510_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
+ devcb_read8 read_port;
+ devcb_write8 write_port;
+
+ uint8_t pullup, floating, dir, port, drive;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
inline uint32_t map(uint16_t adr) {
if(map_enable & (1 << (adr >> 13))) {
@@ -64,6 +67,14 @@ protected:
return adr;
}
+ uint8_t dir_r();
+ void dir_w(uint8_t data);
+ uint8_t port_r();
+ void port_w(uint8_t data);
+
+ void init_port();
+ void update_port();
+
#define O(o) void o ## _full(); void o ## _partial()
// 4510 opcodes
diff --git a/src/devices/cpu/m6502/m50734.cpp b/src/devices/cpu/m6502/m50734.cpp
new file mode 100644
index 00000000000..af58690aa29
--- /dev/null
+++ b/src/devices/cpu/m6502/m50734.cpp
@@ -0,0 +1,473 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Mitsubishi M50734 emulation (preliminary)
+
+ This microcontroller contains no internal memory, RAM or ROM. The
+ external bus allows P05 to be programmed as a strobe (DME) for a
+ separable "data" memory space. On-chip peripherals include an ADC,
+ UART, various general and special-purpose timers and a stepper
+ motor controller.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "m50734.h"
+
+#define LOG_INIT (1U << 1)
+#define LOG_TIMER (1U << 2)
+#define LOG_TIMER_X (1U << 3)
+#define VERBOSE (0)
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(M50734, m50734_device, "m50734", "Mitsubishi M50734")
+
+m50734_device::m50734_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : m740_device(mconfig, M50734, tag, owner, clock)
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_port_in_cb(*this, 0)
+ , m_port_out_cb(*this)
+ , m_analog_in_cb(*this, 0)
+ , m_port_latch{0, 0, 0, 0}
+ , m_port_3state{0, 0, 0, 0}
+ , m_ad_control(0)
+ , m_ad_register(0)
+ , m_prescaler_reload{0xff, 0xff, 0xff}
+ , m_timer_reload{0xff, 0xff, 0xff}
+ , m_step_counter{0, 0}
+ , m_phase_counter(0)
+ , m_smcon{0, 0}
+ , m_tx_count(0)
+ , m_tx_reload(0xffff)
+{
+ program_config.m_internal_map = address_map_constructor(FUNC(m50734_device::internal_map), this);
+}
+
+device_memory_interface::space_config_vector m50734_device::memory_space_config() const
+{
+ space_config_vector scv = m740_device::memory_space_config();
+ if (has_configured_map(AS_DATA))
+ scv.emplace_back(AS_DATA, &m_data_config);
+ return scv;
+}
+
+void m50734_device::device_config_complete()
+{
+ m740_device::device_config_complete();
+
+ for (int n = 0; n < 4; n++)
+ {
+ if (m_port_in_cb[n].isunset())
+ m_port_in_cb[n].bind().set_constant(m_port_3state[n]);
+ }
+}
+
+void m50734_device::step_motor(int which)
+{
+ if (!BIT(m_smcon[which], 2))
+ return;
+
+ if (--m_step_counter[which] == 0 && !BIT(m_interrupt_control[0], which * 2 + 5))
+ {
+ LOGMASKED(LOG_TIMER, "%s counter empty at %s\n", which ? "Vertical" : "Horizontal", machine().time().to_string());
+ m_interrupt_control[0] |= 0x20 << (which * 2);
+ if (BIT(m_interrupt_control[0], which * 2 + 4))
+ set_input_line(M740_INT3_LINE, ASSERT_LINE);
+ }
+
+ // Increment or decrement HPHC/VPHC
+ m_phase_counter = (m_phase_counter + ((BIT(m_smcon[which], 1) ? 7 : 1) << (which * 4))) & 0x77;
+
+ // TODO: single shot mode, phase decoder and P2 output
+}
+
+template <int N>
+TIMER_CALLBACK_MEMBER(m50734_device::timer_interrupt)
+{
+ if (!BIT(m_interrupt_control[1], N * 2 + 1))
+ {
+ m_interrupt_control[1] |= 1 << (N * 2 + 1);
+ if (BIT(m_interrupt_control[1], N * 2))
+ {
+ LOGMASKED(LOG_TIMER, "Timer %d interrupt asserted at %s\n", N + 1, machine().time().to_string());
+ set_input_line(M740_INT2_LINE, ASSERT_LINE);
+ }
+ }
+
+ if (N == 2)
+ step_motor(0); // Timer 3 steps HC
+ else if (N == 0)
+ step_motor(1); // Timer 0 steps VC
+
+ // Reload timer and prescaler
+ m_timer[N]->adjust(clocks_to_attotime(16 * u32(m_prescaler_reload[N] + 1) * (m_timer_reload[N] + 1)));
+}
+
+void m50734_device::device_start()
+{
+ m740_device::device_start();
+
+ space(has_space(AS_DATA) ? AS_DATA : AS_PROGRAM).specific(m_data);
+
+ m_ad_timer = timer_alloc(FUNC(m50734_device::ad_complete), this);
+ m_timer[0] = timer_alloc(FUNC(m50734_device::timer_interrupt<0>), this);
+ m_timer[1] = timer_alloc(FUNC(m50734_device::timer_interrupt<1>), this);
+ m_timer[2] = timer_alloc(FUNC(m50734_device::timer_interrupt<2>), this);
+ m_timer_x = timer_alloc(FUNC(m50734_device::timer_x_interrupt), this);
+
+ save_item(NAME(m_port_latch));
+ save_item(NAME(m_port_direction));
+ save_item(NAME(m_p0_function));
+ save_item(NAME(m_p2_p3_function));
+ save_item(NAME(m_ad_control));
+ save_item(NAME(m_ad_register));
+ save_item(NAME(m_prescaler_reload));
+ save_item(NAME(m_timer_reload));
+ save_item(NAME(m_step_counter));
+ save_item(NAME(m_phase_counter));
+ save_item(NAME(m_smcon));
+ save_item(NAME(m_tx_count));
+ save_item(NAME(m_tx_reload));
+ save_item(NAME(m_interrupt_control));
+}
+
+void m50734_device::device_reset()
+{
+ m740_device::device_reset();
+ SP = 0x01ff;
+
+ // Reset port registers
+ std::fill(std::begin(m_port_direction), std::end(m_port_direction), 0x00);
+ for (int n = 0; n < 4; n++)
+ m_port_out_cb[n](m_port_3state[n]);
+ m_p0_function = 0x00;
+ m_p2_p3_function = 0x00;
+
+ // Reset A-D
+ m_ad_control |= 0x04;
+ m_ad_timer->adjust(attotime::never);
+
+ // Reset stepper motor control registers (datasheet has no implication of RESET affecting these, but mps1200 never fully initializes SMCONH)
+ m_smcon[0] = 0;
+ m_smcon[1] = 0;
+
+ // Reset interrupts
+ std::fill(std::begin(m_interrupt_control), std::end(m_interrupt_control), 0x00);
+ set_input_line(M740_INT2_LINE, CLEAR_LINE);
+ set_input_line(M740_INT3_LINE, CLEAR_LINE);
+ set_input_line(M740_INT4_LINE, CLEAR_LINE);
+
+ // Initialize Timer X
+ set_timer_x(0x0200);
+}
+
+void m50734_device::read_dummy(u16 adr)
+{
+ // M50734 outputs RD and WR strobes rather than R/W, so dummy accesses should do nothing
+}
+
+u8 m50734_device::read_data(u16 adr)
+{
+ if (BIT(m_p0_function, 5))
+ return m_data.read_byte(adr);
+ else
+ return m740_device::read(adr);
+}
+
+void m50734_device::write_data(u16 adr, u8 val)
+{
+ if (BIT(m_p0_function, 5))
+ m_data.write_byte(adr, val);
+ else
+ m740_device::write(adr, val);
+}
+
+u8 m50734_device::interrupt_control_r(offs_t offset)
+{
+ return m_interrupt_control[2 - offset];
+}
+
+// TODO: emulate modes other than timer mode
+static const char *const s_timer_x_modes[4] =
+{
+ "timer",
+ "pulse output",
+ "event count",
+ "PWM"
+};
+
+void m50734_device::interrupt_control_w(offs_t offset, u8 data)
+{
+ if (offset == 1)
+ data &= 0x3f;
+ u8 old_control = std::exchange(m_interrupt_control[2 - offset], data);
+ if (offset == 2)
+ {
+ bool he_ve_interrupt = (data & (data >> 1) & 0x50) != 0;
+ bool old_interrupt = (old_control & (old_control >> 1) & 0x50) != 0;
+ if (he_ve_interrupt != old_interrupt)
+ {
+ LOGMASKED(LOG_TIMER, "%s: HE/VE interrupt %sactivated by write to interrupt control register 1 ($%02X -> $%02X)\n", machine().describe_context(), he_ve_interrupt ? "": "de", old_control, data);
+ set_input_line(M740_INT3_LINE, he_ve_interrupt ? ASSERT_LINE : CLEAR_LINE);
+ }
+ }
+ else if (offset == 1)
+ {
+ bool timer_interrupt = (data & (data >> 1) & 0x15) != 0;
+ bool old_interrupt = (old_control & (old_control >> 1) & 0x15) != 0;
+ if (timer_interrupt != old_interrupt)
+ {
+ LOGMASKED(LOG_TIMER, "%s: Timer interrupt %sactivated by write to interrupt control register 2 ($%02X -> $%02X)\n", machine().describe_context(), timer_interrupt ? "": "de", old_control, data);
+ set_input_line(M740_INT2_LINE, timer_interrupt ? ASSERT_LINE : CLEAR_LINE);
+ }
+ }
+ else
+ {
+ bool tx_run = BIT(data, 0, 2) != 2 && !BIT(data, 2);
+ if (!tx_run && m_timer_x->enabled())
+ {
+ m_tx_count = get_timer_x();
+ LOGMASKED(LOG_TIMER_X, "%s: Timer X count stopped at $%04X in %s mode by write to interrupt control register 3 ($%02X -> $%02X)\n", machine().describe_context(),
+ m_tx_count, s_timer_x_modes[BIT(data, 0, 2)], old_control, data);
+ m_timer_x->enable(false);
+ }
+ else if (tx_run && !m_timer_x->enabled() && (m_tx_count != 0 || m_tx_reload != 0))
+ {
+ LOGMASKED(LOG_TIMER_X, "%s: Timer X count restarted from $%04X in %s mode by write to interrupt control register 3 ($%02X -> $%02X)\n", machine().describe_context(),
+ m_tx_count, s_timer_x_modes[BIT(data, 0, 2)], old_control, data);
+ m_timer_x->adjust(clocks_to_attotime(16 * (m_tx_count != 0 ? m_tx_count : m_tx_reload + 1)));
+ m_timer_x->enable(true);
+ }
+ bool tx_interrupt = (data & (data >> 1) & 0x15) != 0;
+ bool old_interrupt = (old_control & (old_control >> 1) & 0x15) != 0;
+ if (tx_interrupt != old_interrupt)
+ {
+ LOGMASKED(LOG_TIMER_X, "%s: Timer X interrupt %sactivated by write to interrupt control register 3 ($%02X -> $%02X)\n", machine().describe_context(), tx_interrupt ? "": "de", old_control, data);
+ set_input_line(M740_INT4_LINE, tx_interrupt ? ASSERT_LINE : CLEAR_LINE);
+ }
+ }
+}
+
+template <int N>
+u8 m50734_device::port_r(offs_t offset)
+{
+ if (BIT(offset, 0))
+ return m_port_direction[N];
+ else if (m_port_direction[0] == 0xff)
+ return m_port_latch[N];
+ else
+ return (m_port_in_cb[N]() & ~m_port_direction[N]) | (m_port_latch[N] & m_port_direction[N]);
+}
+
+template <int N>
+void m50734_device::port_w(offs_t offset, u8 data)
+{
+ if (BIT(offset, 0))
+ {
+ if (m_port_direction[N] != data)
+ {
+ LOGMASKED(LOG_INIT, "%s: Port P%d direction = $%02X\n", machine().describe_context(), N, data);
+ m_port_direction[N] = data;
+ m_port_out_cb[N]((data & m_port_latch[N]) | (m_port_3state[N] & ~m_port_direction[N]));
+ }
+ }
+ else if (((std::exchange(m_port_latch[N], data) ^ data) & m_port_direction[N]) != 0)
+ m_port_out_cb[N]((data & m_port_direction[N]) | (m_port_3state[N] & ~m_port_direction[N]));
+}
+
+u8 m50734_device::p4_r()
+{
+ // P4 has only 4 pins and no output drivers
+ return m_port_in_cb[4]() & 0x0f;
+}
+
+u8 m50734_device::p0_function_r()
+{
+ return m_p0_function;
+}
+
+void m50734_device::p0_function_w(u8 data)
+{
+ LOGMASKED(LOG_INIT, "%s: Port P0 function = $%02X\n", machine().describe_context(), data);
+ m_p0_function = data;
+}
+
+u8 m50734_device::p2_p3_function_r()
+{
+ return m_p2_p3_function;
+}
+
+void m50734_device::p2_p3_function_w(u8 data)
+{
+ LOGMASKED(LOG_INIT, "%s: Port P2/P3 function = $%02X\n", machine().describe_context(), data);
+ m_p2_p3_function = data & 0xc7;
+}
+
+u8 m50734_device::ad_control_r()
+{
+ return m_ad_control;
+}
+
+void m50734_device::ad_control_w(u8 data)
+{
+ m_ad_control = data & 0x03;
+ m_ad_timer->adjust(cycles_to_attotime(72)); // 36 µsec at 8 MHz
+}
+
+TIMER_CALLBACK_MEMBER(m50734_device::ad_complete)
+{
+ m_ad_register = m_analog_in_cb[m_ad_control & 0x03]();
+ m_ad_control |= 0x04;
+}
+
+u8 m50734_device::ad_r()
+{
+ return m_ad_register;
+}
+
+u8 m50734_device::timer_r(offs_t offset)
+{
+ if (!m_timer[offset >> 1]->enabled())
+ return 0;
+
+ u32 ticks = attotime_to_clocks(m_timer[offset >> 1]->remaining()) / 16;
+ u8 pre = m_prescaler_reload[offset >> 1];
+ if (BIT(offset, 0))
+ return std::min<u32>(ticks / (pre + 1), 0xff);
+ else
+ return ticks % (pre + 1);
+}
+
+void m50734_device::timer_w(offs_t offset, u8 data)
+{
+ u32 ticks = m_timer[offset >> 1]->enabled() ? attotime_to_clocks(m_timer[offset >> 1]->remaining()) / 16 : 0x10000;
+ u8 pre = m_prescaler_reload[offset >> 1];
+ if (BIT(offset, 0))
+ {
+ attotime expire_time = clocks_to_attotime(16 * (data * pre + (ticks % (pre + 1)) + 1));
+ LOGMASKED(LOG_INIT, "%s: Reload timer %d latch = %u (expires in %.1f usec)\n", machine().describe_context(), (offset >> 1) + 1, data, expire_time.as_double() * 1.0E6);
+ m_timer_reload[offset >> 1] = data;
+ m_timer[offset >> 1]->adjust(expire_time);
+ }
+ else
+ {
+ attotime expire_time = clocks_to_attotime(16 * (data + 1) * (std::min<u32>(ticks / (pre + 1), 0xff) + 1));
+ LOGMASKED(LOG_INIT, "%s: Reload prescaler %d latch = %u (expires in %.1f usec)\n", machine().describe_context(), (offset >> 1) + 1, data, expire_time.as_double() * 1.0E6);
+ m_prescaler_reload[offset >> 1] = data;
+ m_timer[offset >> 1]->adjust(expire_time);
+ }
+}
+
+u8 m50734_device::step_counter_r(offs_t offset)
+{
+ return m_step_counter[offset];
+}
+
+void m50734_device::step_counter_w(offs_t offset, u8 data)
+{
+ LOGMASKED(LOG_INIT, "%s: %s counter = %u steps\n", machine().describe_context(), BIT(offset, 0) ? "Vertical" : "Horizontal", data);
+ m_step_counter[offset] = data;
+}
+
+u8 m50734_device::phase_counter_r()
+{
+ return m_phase_counter;
+}
+
+void m50734_device::phase_counter_w(u8 data)
+{
+ // HPHC and VPHC are 3-bit counters (TODO: P2 output)
+ m_phase_counter = data & 0x77;
+}
+
+u8 m50734_device::smcon_r(offs_t offset)
+{
+ return m_smcon[offset];
+}
+
+void m50734_device::smcon_w(offs_t offset, u8 data)
+{
+ if (m_smcon[offset] != (data & 0x0f))
+ LOGMASKED(LOG_INIT, "%s: SMCON%c = $%02X\n", machine().describe_context(), "HV"[offset], data);
+ m_smcon[offset] = data & 0x0f;
+}
+
+TIMER_CALLBACK_MEMBER(m50734_device::timer_x_interrupt)
+{
+ if (!BIT(m_interrupt_control[2], 5))
+ {
+ m_interrupt_control[2] |= 0x20;
+ if (BIT(m_interrupt_control[2], 4))
+ {
+ LOGMASKED(LOG_TIMER_X, "Timer X interrupt asserted at %s\n", machine().time().to_string());
+ set_input_line(M740_INT4_LINE, ASSERT_LINE);
+ }
+ }
+
+ if (m_tx_reload != 0)
+ m_timer_x->adjust(clocks_to_attotime(16 * (m_tx_reload + 1)));
+ else
+ {
+ m_tx_count = 0;
+ m_timer_x->enable(false);
+ }
+}
+
+u16 m50734_device::get_timer_x() const
+{
+ if (m_timer_x->enabled())
+ {
+ unsigned count = attotime_to_clocks(m_timer_x->remaining()) / 16;
+ return count > m_tx_reload ? 0 : count;
+ }
+ else
+ return m_tx_count;
+}
+
+void m50734_device::set_timer_x(u16 count)
+{
+ LOGMASKED(LOG_TIMER_X, "%s: Timer X reload value = $%04X (%s mode)\n", machine().describe_context(), count, s_timer_x_modes[BIT(m_interrupt_control[2], 0, 2)]);
+ m_tx_reload = count;
+ if (BIT(m_interrupt_control[2], 0, 2) != 2 && !BIT(m_interrupt_control[2], 2))
+ {
+ m_timer_x->adjust(clocks_to_attotime(16 * count));
+ m_timer_x->enable(true);
+ }
+ else
+ m_tx_count = count;
+}
+
+u8 m50734_device::timer_x_r(offs_t offset)
+{
+ return BIT(get_timer_x(), BIT(offset, 0) ? 8 : 0, 8);
+}
+
+void m50734_device::timer_x_w(offs_t offset, u8 data)
+{
+ if (BIT(offset, 0))
+ set_timer_x(data << 8 | (m_tx_reload & 0x00ff));
+ else
+ set_timer_x(data | (m_tx_reload & 0xff00));
+}
+
+void m50734_device::internal_map(address_map &map)
+{
+ // TODO: other timers, UART, etc.
+ map(0x00da, 0x00db).rw(FUNC(m50734_device::timer_x_r), FUNC(m50734_device::timer_x_w));
+ map(0x00dc, 0x00e1).rw(FUNC(m50734_device::timer_r), FUNC(m50734_device::timer_w));
+ map(0x00e2, 0x00e3).rw(FUNC(m50734_device::step_counter_r), FUNC(m50734_device::step_counter_w));
+ map(0x00e9, 0x00e9).rw(FUNC(m50734_device::ad_control_r), FUNC(m50734_device::ad_control_w));
+ map(0x00ea, 0x00ea).r(FUNC(m50734_device::ad_r));
+ map(0x00eb, 0x00eb).r(FUNC(m50734_device::p4_r));
+ map(0x00ec, 0x00ec).rw(FUNC(m50734_device::phase_counter_r), FUNC(m50734_device::phase_counter_w));
+ map(0x00ed, 0x00ed).rw(FUNC(m50734_device::p2_p3_function_r), FUNC(m50734_device::p2_p3_function_w));
+ map(0x00ee, 0x00ef).rw(FUNC(m50734_device::port_r<3>), FUNC(m50734_device::port_w<3>));
+ map(0x00f0, 0x00f1).rw(FUNC(m50734_device::port_r<2>), FUNC(m50734_device::port_w<2>));
+ map(0x00f3, 0x00f4).rw(FUNC(m50734_device::port_r<1>), FUNC(m50734_device::port_w<1>));
+ map(0x00f5, 0x00f5).rw(FUNC(m50734_device::p0_function_r), FUNC(m50734_device::p0_function_w));
+ map(0x00f6, 0x00f7).rw(FUNC(m50734_device::port_r<0>), FUNC(m50734_device::port_w<0>));
+ map(0x00f8, 0x00f9).rw(FUNC(m50734_device::smcon_r), FUNC(m50734_device::smcon_w));
+ map(0x00fd, 0x00ff).rw(FUNC(m50734_device::interrupt_control_r), FUNC(m50734_device::interrupt_control_w));
+}
diff --git a/src/devices/cpu/m6502/m50734.h b/src/devices/cpu/m6502/m50734.h
new file mode 100644
index 00000000000..a8c8a9a093c
--- /dev/null
+++ b/src/devices/cpu/m6502/m50734.h
@@ -0,0 +1,160 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Mitsubishi M50734
+
+**********************************************************************
+ _____ _____
+ P04/STBout 1 |* \_/ | 64 Vcc
+ P05/_DME 2 | | 63 P03/BUSYout
+ P06/TxD 3 | | 62 P02/CNTR
+ P07/RxD 4 | | 61 P01/_INT2
+ P10 5 | | 60 P00/_INT1
+ P11 6 | | 59 WDout
+ P12 7 | | 58 A0/D0
+ P13 8 | | 57 A1/D1
+ P14 9 | | 56 A2/D2
+ P15 10 | | 55 A3/D3
+ P16 11 | | 54 A4/D4
+ P17 12 | | 53 A5/D5
+ P20/Ha 13 | | 52 A6/D6
+ P21/Hb 14 | | 51 A7/D7
+ P22/Hc 15 | M50734SP | 50 ALE
+ P23/Hd 16 | | 49 A8
+ P24/Va 17 | | 48 A9
+ P25/Vb 18 | | 47 A10
+ P26/Vc 19 | | 46 A11
+ P27/Vd 20 | | 45 A12
+ P30/PWMout 21 | | 44 A13
+ P31/Sclk 22 | | 43 A14
+ P32/Sio 23 | | 42 A15
+ P33 24 | | 41 SYNC
+ P34 25 | | 40 ɸ
+ P35 26 | | 39 _WR
+ P36 27 | | 38 _RD
+ P37 28 | | 37 Vref
+ _RESET 29 | | 36 P43/AN3
+ Xin 30 | | 35 P42/AN2
+ Xout 31 | | 34 P41/AN1
+ Vss 32 |_____________| 33 P40/AN0
+
+**********************************************************************/
+
+#ifndef MAME_CPU_M6502_M50734_H
+#define MAME_CPU_M6502_M50734_H
+
+#pragma once
+
+#include "m740.h"
+
+class m50734_device : public m740_device
+{
+public:
+ m50734_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // port callback configuration
+ auto p0_in_cb() { return m_port_in_cb[0].bind(); }
+ auto p0_out_cb() { return m_port_out_cb[0].bind(); }
+ auto p1_in_cb() { return m_port_in_cb[1].bind(); }
+ auto p1_out_cb() { return m_port_out_cb[1].bind(); }
+ auto p2_in_cb() { return m_port_in_cb[2].bind(); }
+ auto p2_out_cb() { return m_port_out_cb[2].bind(); }
+ auto p3_in_cb() { return m_port_in_cb[3].bind(); }
+ auto p3_out_cb() { return m_port_out_cb[3].bind(); }
+ auto p4_in_cb() { return m_port_in_cb[4].bind(); }
+ auto an0_in_cb() { return m_analog_in_cb[0].bind(); }
+ auto an1_in_cb() { return m_analog_in_cb[1].bind(); }
+ auto an2_in_cb() { return m_analog_in_cb[2].bind(); }
+ auto an3_in_cb() { return m_analog_in_cb[3].bind(); }
+
+ // port three-state output configuration
+ void set_p0_3state(u8 value) { assert(!configured()); m_port_3state[0] = value; }
+ void set_p1_3state(u8 value) { assert(!configured()); m_port_3state[1] = value; }
+ void set_p2_3state(u8 value) { assert(!configured()); m_port_3state[2] = value; }
+ void set_p3_3state(u8 value) { assert(!configured()); m_port_3state[3] = value; }
+
+protected:
+ // device_t implementation
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_execute_interface implementation
+ virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
+ virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); }
+
+ // device_memory_interface implementation
+ space_config_vector memory_space_config() const override;
+
+ // m740_device overrides
+ virtual void read_dummy(u16 adr) override;
+ virtual uint8_t read_data(u16 adr) override;
+ virtual void write_data(u16 adr, u8 val) override;
+
+private:
+ u8 interrupt_control_r(offs_t offset);
+ void interrupt_control_w(offs_t offset, u8 data);
+
+ template <int N> u8 port_r(offs_t offset);
+ template <int N> void port_w(offs_t offset, u8 data);
+ u8 p4_r();
+ u8 p0_function_r();
+ void p0_function_w(u8 data);
+ u8 p2_p3_function_r();
+ void p2_p3_function_w(u8 data);
+
+ u8 ad_control_r();
+ void ad_control_w(u8 data);
+ u8 ad_r();
+ TIMER_CALLBACK_MEMBER(ad_complete);
+
+ u8 timer_r(offs_t offset);
+ void timer_w(offs_t offset, u8 data);
+ void step_motor(int which);
+ template <int N> TIMER_CALLBACK_MEMBER(timer_interrupt);
+ u8 step_counter_r(offs_t offset);
+ void step_counter_w(offs_t offset, u8 data);
+ u8 phase_counter_r();
+ void phase_counter_w(u8 data);
+ u8 smcon_r(offs_t offset);
+ void smcon_w(offs_t offset, u8 data);
+ TIMER_CALLBACK_MEMBER(timer_x_interrupt);
+ u16 get_timer_x() const;
+ void set_timer_x(u16 count);
+ u8 timer_x_r(offs_t offset);
+ void timer_x_w(offs_t offset, u8 data);
+
+ void internal_map(address_map &map) ATTR_COLD;
+
+ const address_space_config m_data_config;
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_data;
+
+ devcb_read8::array<5> m_port_in_cb;
+ devcb_write8::array<4> m_port_out_cb;
+ devcb_read8::array<4> m_analog_in_cb;
+
+ emu_timer *m_ad_timer;
+ emu_timer *m_timer[3];
+ emu_timer *m_timer_x;
+
+ u8 m_port_latch[4];
+ u8 m_port_direction[4];
+ u8 m_port_3state[4];
+ u8 m_p0_function;
+ u8 m_p2_p3_function;
+ u8 m_ad_control;
+ u8 m_ad_register;
+ u8 m_prescaler_reload[3];
+ u8 m_timer_reload[3];
+ u8 m_step_counter[2];
+ u8 m_phase_counter;
+ u8 m_smcon[2];
+ u16 m_tx_count;
+ u16 m_tx_reload;
+ u8 m_interrupt_control[3];
+};
+
+DECLARE_DEVICE_TYPE(M50734, m50734_device)
+
+#endif // MAME_CPU_M6502_M50734_H
diff --git a/src/devices/cpu/m6502/m5074x.cpp b/src/devices/cpu/m6502/m5074x.cpp
index 9626dc0d9ad..3295f2d28a9 100644
--- a/src/devices/cpu/m6502/m5074x.cpp
+++ b/src/devices/cpu/m6502/m5074x.cpp
@@ -1,29 +1,36 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont, Olivier Galibert
/*
- Mitsubishi M5074x 8-bit microcontroller family
+ Mitsubishi M5074x/5075x 8-bit microcontroller family
*/
#include "emu.h"
#include "m5074x.h"
+#define LOG_ADC (1U << 1)
+#define LOG_PORTS (1U << 2)
+#define LOG_TIMER (1U << 3)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
-#define IRQ_CNTRREQ (0x80)
-#define IRQ_CNTRENA (0x40)
-#define IRQ_TMR1REQ (0x20)
-#define IRQ_TMR1ENA (0x10)
-#define IRQ_TMR2REQ (0x08)
-#define IRQ_TMR2ENA (0x04)
-#define IRQ_INTREQ (0x02)
-#define IRQ_INTENA (0x01)
+static constexpr u8 IRQ_CNTRREQ = 0x80;
+static constexpr u8 IRQ_CNTRENA = 0x40;
+static constexpr u8 IRQ_TMR1REQ = 0x20;
+static constexpr u8 IRQ_TMR1ENA = 0x10;
+static constexpr u8 IRQ_TMR2REQ = 0x08;
+static constexpr u8 IRQ_TMR2ENA = 0x04;
+static constexpr u8 IRQ_INTREQ = 0x02;
+static constexpr u8 IRQ_INTENA = 0x01;
-#define TMRC_TMRXREQ (0x80)
-#define TMRC_TMRXENA (0x40)
-#define TMRC_TMRXHLT (0x20)
-#define TMRC_TMRXMDE (0x0c)
+static constexpr u8 TMRC_TMRXREQ = 0x80;
+static constexpr u8 TMRC_TMRXENA = 0x40;
+static constexpr u8 TMRC_TMRXHLT = 0x20;
+static constexpr u8 TMRC_TMRXMDE = 0x0c;
//**************************************************************************
// DEVICE DEFINITIONS
@@ -31,6 +38,7 @@
DEFINE_DEVICE_TYPE(M50740, m50740_device, "m50740", "Mitsubishi M50740")
DEFINE_DEVICE_TYPE(M50741, m50741_device, "m50741", "Mitsubishi M50741")
+DEFINE_DEVICE_TYPE(M50753, m50753_device, "m50753", "Mitsubishi M50753")
//**************************************************************************
// LIVE DEVICE
@@ -39,11 +47,11 @@ DEFINE_DEVICE_TYPE(M50741, m50741_device, "m50741", "Mitsubishi M50741")
//-------------------------------------------------
// m5074x_device - constructor
//-------------------------------------------------
-m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map) :
+m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addrbits, address_map_constructor internal_map) :
m740_device(mconfig, type, tag, owner, clock),
- m_program_config("program", ENDIANNESS_LITTLE, 8, 13, 0, internal_map),
- m_read_p{{*this}, {*this}, {*this}, {*this}},
- m_write_p{{*this}, {*this}, {*this}, {*this}},
+ m_program_config("program", ENDIANNESS_LITTLE, 8, addrbits, 0, internal_map),
+ m_read_p(*this, 0),
+ m_write_p(*this),
m_intctrl(0),
m_tmrctrl(0),
m_tmr12pre(0),
@@ -56,6 +64,7 @@ m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, co
m_tmrxlatch(0),
m_last_all_ints(0)
{
+ std::fill(std::begin(m_pullups), std::end(m_pullups), 0);
}
//-------------------------------------------------
@@ -64,16 +73,10 @@ m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, co
void m5074x_device::device_start()
{
- for (int i = 0; i < 4; i++)
- {
- m_read_p[i].resolve_safe(0);
- m_write_p[i].resolve_safe();
- }
-
- for (int i = 0; i < NUM_TIMERS; i++)
- {
- m_timers[i] = timer_alloc(i, nullptr);
- }
+ m_timers[TIMER_1] = timer_alloc(FUNC(m5074x_device::timer1_tick), this);
+ m_timers[TIMER_2] = timer_alloc(FUNC(m5074x_device::timer2_tick), this);
+ m_timers[TIMER_X] = timer_alloc(FUNC(m5074x_device::timerx_tick), this);
+ m_timers[TIMER_ADC] = timer_alloc(FUNC(m5074x_device::adc_complete), this);
m740_device::device_start();
@@ -123,42 +126,39 @@ void m5074x_device::device_reset()
m_tmr1 = m_tmr2 = m_tmrx = 0;
}
-void m5074x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(m5074x_device::timer1_tick)
{
- switch (id)
- {
- case TIMER_1:
- m_tmr1--;
+ m_tmr1--;
- if (m_tmr1 <= 0)
- {
- m_intctrl |= IRQ_TMR1REQ;
- m_tmr1 = m_tmr1latch;
- recalc_irqs();
- }
- break;
+ if (m_tmr1 <= 0)
+ {
+ m_intctrl |= IRQ_TMR1REQ;
+ m_tmr1 = m_tmr1latch;
+ recalc_irqs();
+ }
+}
- case TIMER_2:
- m_tmr2--;
+TIMER_CALLBACK_MEMBER(m5074x_device::timer2_tick)
+{
+ m_tmr2--;
- if (m_tmr2 <= 0)
- {
- m_intctrl |= IRQ_TMR2REQ;
- m_tmr2 = m_tmr2latch;
- recalc_irqs();
- }
- break;
+ if (m_tmr2 <= 0)
+ {
+ m_intctrl |= IRQ_TMR2REQ;
+ m_tmr2 = m_tmr2latch;
+ recalc_irqs();
+ }
+}
- case TIMER_X:
- m_tmrx--;
+TIMER_CALLBACK_MEMBER(m5074x_device::timerx_tick)
+{
+ m_tmrx--;
- if (m_tmrx <= 0)
- {
- m_tmrctrl |= TMRC_TMRXREQ;
- m_tmrx = m_tmrxlatch;
- recalc_irqs();
- }
- break;
+ if (m_tmrx == 0)
+ {
+ m_tmrctrl |= TMRC_TMRXREQ;
+ m_tmrx = m_tmrxlatch;
+ recalc_irqs();
}
}
@@ -166,20 +166,13 @@ void m5074x_device::execute_set_input(int inputnum, int state)
{
switch (inputnum)
{
- case M5074X_INT1_LINE:
- if (state == ASSERT_LINE)
- {
- m_intctrl |= IRQ_INTREQ;
- }
- else
- {
- m_intctrl &= ~IRQ_INTREQ;
- }
- break;
-
- case M5074X_SET_OVERFLOW: // the base 740 class can handle this
- m740_device::execute_set_input(M740_SET_OVERFLOW, state);
- break;
+ case M5074X_INT1_LINE:
+ // FIXME: edge-triggered
+ if (state == ASSERT_LINE)
+ {
+ m_intctrl |= IRQ_INTREQ;
+ }
+ break;
}
recalc_irqs();
@@ -244,12 +237,14 @@ void m5074x_device::recalc_timer(int timer)
case 0:
hz = clock() / 16;
hz /= (m_tmr12pre + 2);
+ LOGMASKED(LOG_TIMER, "%s: timer 1, prescale %02x, fire at %d Hz\n", machine().describe_context(), m_tmr12pre, hz);
m_timers[TIMER_1]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
break;
case 1:
hz = clock() / 16;
hz /= (m_tmr12pre + 2);
+ LOGMASKED(LOG_TIMER, "%s: timer 2, prescale %02x, fire at %d Hz\n", machine().describe_context(), m_tmr12pre, hz);
m_timers[TIMER_2]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
break;
@@ -261,12 +256,14 @@ void m5074x_device::recalc_timer(int timer)
// stop bit?
if (m_tmrctrl & TMRC_TMRXHLT)
{
+ LOGMASKED(LOG_TIMER, "%s: timer X halted\n", machine().describe_context());
m_timers[TIMER_X]->adjust(attotime::never, 0, attotime::never);
}
else
{
hz = clock() / 16;
hz /= (m_tmrxpre + 2);
+ LOGMASKED(LOG_TIMER, "%s: timer X, prescale %02x, fire at %d Hz\n", machine().describe_context(), m_tmrxpre, hz);
m_timers[TIMER_X]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
}
}
@@ -278,8 +275,11 @@ void m5074x_device::recalc_timer(int timer)
}
}
-void m5074x_device::send_port(address_space &space, uint8_t offset, uint8_t data)
+void m5074x_device::send_port(uint8_t offset, uint8_t data)
{
+ LOGMASKED(LOG_PORTS, "%s: Write port %d, data %02x DDR %02x pull-ups %02x\n", machine().describe_context(), offset,
+ data, m_ddrs[offset], m_pullups[offset]);
+
m_write_p[offset](data);
}
@@ -292,10 +292,13 @@ uint8_t m5074x_device::read_port(uint8_t offset)
// OR in ddr-masked version of port writes
incoming |= (m_ports[offset] & m_ddrs[offset]);
+ LOGMASKED(LOG_PORTS, "%s: Read port %d, incoming %02x DDR %02x output latch %02x\n", machine().describe_context(), offset,
+ m_read_p[offset](), m_ddrs[offset], m_ports[offset]);
+
return incoming;
}
-READ8_MEMBER(m5074x_device::ports_r)
+uint8_t m5074x_device::ports_r(offs_t offset)
{
switch (offset)
{
@@ -322,58 +325,74 @@ READ8_MEMBER(m5074x_device::ports_r)
case 9:
return m_ddrs[3];
+
+ case 0xa:
+ return read_port(4) & 0x0f;
+
+ case 0xb:
+ return m_ddrs[4];
}
return 0xff;
}
-WRITE8_MEMBER(m5074x_device::ports_w)
+void m5074x_device::ports_w(offs_t offset, uint8_t data)
{
switch (offset)
{
case 0: // p0
- send_port(space, 0, data & m_ddrs[0]);
+ send_port(0, (data & m_ddrs[0]) | (m_pullups[0] & ~m_ddrs[0]));
m_ports[0] = data;
break;
case 1: // p0 ddr
- send_port(space, 0, m_ports[0] & data);
+ send_port(0, (m_ports[0] & data) | (m_pullups[0] & ~data));
m_ddrs[0] = data;
break;
case 2: // p1
- send_port(space, 1, data & m_ddrs[1]);
+ send_port(1, (data & m_ddrs[1]) | (m_pullups[1] & ~m_ddrs[1]));
m_ports[1] = data;
break;
case 3: // p1 ddr
- send_port(space, 1, m_ports[1] & data);
+ send_port(1, (m_ports[1] & data) | (m_pullups[1] & ~data));
m_ddrs[1] = data;
break;
case 4: // p2
- send_port(space, 2, data & m_ddrs[2]);
+ send_port(2, (data & m_ddrs[2]) | (m_pullups[2] & ~m_ddrs[2]));
m_ports[2] = data;
break;
case 5: // p2 ddr
- send_port(space, 2, m_ports[2] & data);
+ send_port(2, (m_ports[2] & data) | (m_pullups[2] & ~data));
m_ddrs[2] = data;
break;
case 8: // p3
- send_port(space, 3, data & m_ddrs[3]);
+ send_port(3, (data & m_ddrs[3]) | (m_pullups[3] & ~m_ddrs[3]));
m_ports[3] = data;
break;
case 9: // p3 ddr
- send_port(space, 3, m_ports[3] & data);
+ send_port(3, (m_ports[3] & data) | (m_pullups[3] & ~data));
m_ddrs[3] = data;
break;
+
+ case 0xa: // p4 (4-bit open drain)
+ send_port(4, (data & m_ddrs[4] & 0x0f) | (m_pullups[4] & ~m_ddrs[4]));
+ m_ports[4] = data & 0x0f;
+ break;
+
+ case 0xb: // p4 ddr
+ send_port(4, (m_ports[4] & data & 0x0f) | (m_pullups[4] & ~data));
+ m_ddrs[4] = data & 0x0f;
+ break;
}
}
-READ8_MEMBER(m5074x_device::tmrirq_r)
+uint8_t m5074x_device::tmrirq_r(offs_t offset)
{
switch (offset)
{
@@ -402,54 +421,58 @@ READ8_MEMBER(m5074x_device::tmrirq_r)
return 0xff;
}
-WRITE8_MEMBER(m5074x_device::tmrirq_w)
+void m5074x_device::tmrirq_w(offs_t offset, uint8_t data)
{
-// printf("%02x to tmrirq @ %d\n", data, offset);
-
switch (offset)
{
case 0:
m_tmr12pre = data;
+ LOGMASKED(LOG_TIMER, "%s: timer 1/2 prescale %02x\n", machine().describe_context(), data);
recalc_timer(0);
recalc_timer(1);
break;
case 1:
m_tmr1 = m_tmr1latch = data;
+ LOGMASKED(LOG_TIMER, "%s: timer 1 latch %02x\n", machine().describe_context(), data);
break;
case 2:
m_tmr2 = m_tmr2latch = data;
+ LOGMASKED(LOG_TIMER, "%s: timer 2 latch %02x\n", machine().describe_context(), data);
break;
case 3:
- m_tmrxpre = m_tmrxlatch = data;
+ m_tmrxpre = data;
+ LOGMASKED(LOG_TIMER, "%s: timer X prescale %02x\n", machine().describe_context(), data);
recalc_timer(2);
break;
case 4:
- m_tmrx = data;
+ m_tmrx = m_tmrxlatch = data;
+ LOGMASKED(LOG_TIMER, "%s: timer X latch %02x\n", machine().describe_context(), data);
break;
case 5:
- m_intctrl = data;
+ // Interrupt request bits can only be reset
+ m_intctrl = data & (m_intctrl | ~(IRQ_CNTRREQ | IRQ_INTREQ));
recalc_irqs();
break;
case 6:
- m_tmrctrl = data;
+ m_tmrctrl = data & (m_tmrctrl | ~TMRC_TMRXREQ);
recalc_irqs();
break;
}
}
-/* M50740 - baseline for this familiy */
+// M50740 - baseline for this family
void m50740_device::m50740_map(address_map &map)
{
map(0x0000, 0x005f).ram();
map(0x00e0, 0x00e9).rw(FUNC(m50740_device::ports_r), FUNC(m50740_device::ports_w));
map(0x00f9, 0x00ff).rw(FUNC(m50740_device::tmrirq_r), FUNC(m50740_device::tmrirq_w));
- map(0x1400, 0x1fff).rom().region(M5074X_INTERNAL_ROM_REGION, 0);
+ map(0x1400, 0x1fff).rom().region(DEVICE_SELF, 0);
}
m50740_device::m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -458,17 +481,17 @@ m50740_device::m50740_device(const machine_config &mconfig, const char *tag, dev
}
m50740_device::m50740_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m5074x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(m50740_device::m50740_map), this))
+ m5074x_device(mconfig, type, tag, owner, clock, 13, address_map_constructor(FUNC(m50740_device::m50740_map), this))
{
}
-/* M50741 - 50740 with a larger internal ROM */
+// M50741 - 50740 with a larger internal ROM
void m50741_device::m50741_map(address_map &map)
{
map(0x0000, 0x005f).ram();
map(0x00e0, 0x00e9).rw(FUNC(m50741_device::ports_r), FUNC(m50741_device::ports_w));
map(0x00f9, 0x00ff).rw(FUNC(m50741_device::tmrirq_r), FUNC(m50741_device::tmrirq_w));
- map(0x1000, 0x1fff).rom().region("internal", 0);
+ map(0x1000, 0x1fff).rom().region(DEVICE_SELF, 0);
}
m50741_device::m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -477,6 +500,133 @@ m50741_device::m50741_device(const machine_config &mconfig, const char *tag, dev
}
m50741_device::m50741_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m5074x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(m50741_device::m50741_map), this))
+ m5074x_device(mconfig, type, tag, owner, clock, 13, address_map_constructor(FUNC(m50741_device::m50741_map), this))
+{
+}
+
+// M50753 - M5074X with more pins, more RAM, more ROM, A-D, PWM, serial I/O (TODO)
+void m50753_device::m50753_map(address_map &map)
+{
+ map(0x0000, 0x00bf).ram();
+ map(0x00e0, 0x00eb).rw(FUNC(m50753_device::ports_r), FUNC(m50753_device::ports_w));
+ map(0x00ee, 0x00ee).r(FUNC(m50753_device::in_r));
+ map(0x00ef, 0x00ef).r(FUNC(m50753_device::ad_r));
+ map(0x00f2, 0x00f2).nopr().w(FUNC(m50753_device::ad_start_w));
+ map(0x00f3, 0x00f3).rw(FUNC(m50753_device::ad_control_r), FUNC(m50753_device::ad_control_w));
+ map(0x00f5, 0x00f5).rw(FUNC(m50753_device::pwm_control_r), FUNC(m50753_device::pwm_control_w));
+ map(0x00f9, 0x00ff).rw(FUNC(m50753_device::tmrirq_r), FUNC(m50753_device::tmrirq_w));
+ map(0xe800, 0xffff).rom().region(DEVICE_SELF, 0);
+}
+
+// interrupt bits on 50753 are slightly different from the 740/741.
+static constexpr u8 IRQ_50753_INT1REQ = 0x80;
+static constexpr u8 IRQ_50753_INTADC = 0x20;
+static constexpr u8 IRQ_50753_INT2REQ = 0x02;
+
+m50753_device::m50753_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m50753_device(mconfig, M50753, tag, owner, clock)
+{
+}
+
+m50753_device::m50753_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ m5074x_device(mconfig, type, tag, owner, clock, 16, address_map_constructor(FUNC(m50753_device::m50753_map), this)),
+ m_ad_in(*this, 0),
+ m_in_p(*this, 0),
+ m_ad_control(0),
+ m_pwm_enabled(false)
+{
+}
+
+void m50753_device::device_start()
+{
+ m5074x_device::device_start();
+
+ save_item(NAME(m_ad_control));
+ save_item(NAME(m_pwm_enabled));
+}
+
+void m50753_device::device_reset()
{
+ m5074x_device::device_reset();
+
+ m_ad_control = 0;
+ m_pwm_enabled = false;
+}
+
+uint8_t m50753_device::in_r()
+{
+ return m_in_p();
+}
+
+uint8_t m50753_device::ad_r()
+{
+ m_intctrl &= ~IRQ_50753_INTADC;
+ recalc_irqs();
+
+ return m_ad_in[m_ad_control & 0x07]();
+}
+
+void m50753_device::ad_start_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: A-D start (IN%d)\n", machine().describe_context(), m_ad_control & 0x07);
+
+ // starting a conversion. M50753 documentation says conversion time is 72 microseconds.
+ m_timers[TIMER_ADC]->adjust(attotime::from_usec(72));
+}
+
+uint8_t m50753_device::ad_control_r()
+{
+ return m_ad_control;
+}
+
+void m50753_device::ad_control_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: %02x to A-D control\n", machine().describe_context(), data);
+ m_ad_control = data & 0x0f;
+}
+
+uint8_t m50753_device::pwm_control_r()
+{
+ return m_pwm_enabled ? 0x01 : 0x00;
+}
+
+void m50753_device::pwm_control_w(uint8_t data)
+{
+ m_pwm_enabled = BIT(data, 0);
+}
+
+void m50753_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case M50753_INT1_LINE:
+ // FIXME: edge-triggered
+ if (state == ASSERT_LINE)
+ {
+ m_intctrl |= IRQ_50753_INT1REQ;
+ }
+ break;
+
+ case M50753_INT2_LINE:
+ // FIXME: edge-triggered
+ if (state == ASSERT_LINE)
+ {
+ m_intctrl |= IRQ_50753_INT2REQ;
+ }
+ break;
+ }
+
+ recalc_irqs();
+}
+
+TIMER_CALLBACK_MEMBER(m50753_device::adc_complete)
+{
+ m_timers[TIMER_ADC]->adjust(attotime::never);
+
+ // if interrupt source is the ADC, do it.
+ if (m_ad_control & 4)
+ {
+ m_intctrl |= IRQ_50753_INTADC;
+ recalc_irqs();
+ }
}
diff --git a/src/devices/cpu/m6502/m5074x.h b/src/devices/cpu/m6502/m5074x.h
index 1729ff39d25..f466f212573 100644
--- a/src/devices/cpu/m6502/m5074x.h
+++ b/src/devices/cpu/m6502/m5074x.h
@@ -8,14 +8,6 @@
#include "m740.h"
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// internal ROM region
-#define M5074X_INTERNAL_ROM_REGION "internal"
-#define M5074X_INTERNAL_ROM(_tag) (_tag ":" M5074X_INTERNAL_ROM_REGION)
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -25,12 +17,11 @@ class m5074x_device : public m740_device
{
friend class m50740_device;
friend class m50741_device;
+ friend class m50753_device;
enum
{
- M5074X_INT1_LINE = INPUT_LINE_IRQ0,
-
- M5074X_SET_OVERFLOW = M740_SET_OVERFLOW
+ M5074X_INT1_LINE = INPUT_LINE_IRQ0
};
enum
@@ -39,6 +30,8 @@ class m5074x_device : public m740_device
TIMER_2,
TIMER_X,
+ TIMER_ADC,
+
NUM_TIMERS
};
@@ -47,35 +40,44 @@ public:
template <std::size_t Bit> auto read_p() { return m_read_p[Bit].bind(); }
template <std::size_t Bit> auto write_p() { return m_write_p[Bit].bind(); }
+ template <std::size_t Bit> void set_pullups(u8 mask) { m_pullups[Bit] = mask; }
- devcb_read8 m_read_p[4];
- devcb_write8 m_write_p[4];
-
- DECLARE_READ8_MEMBER(ports_r);
- DECLARE_WRITE8_MEMBER(ports_w);
- DECLARE_READ8_MEMBER(tmrirq_r);
- DECLARE_WRITE8_MEMBER(tmrirq_w);
+ uint8_t ports_r(offs_t offset);
+ void ports_w(offs_t offset, uint8_t data);
+ uint8_t tmrirq_r(offs_t offset);
+ void tmrirq_w(offs_t offset, uint8_t data);
bool are_port_bits_output(uint8_t port, uint8_t mask) { return ((m_ddrs[port] & mask) == mask) ? true : false; }
protected:
// construction/destruction
- m5074x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map);
+ m5074x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addrbits, address_map_constructor internal_map);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void execute_set_input(int inputnum, int state) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual space_config_vector memory_space_config() const override;
- void send_port(address_space &space, uint8_t offset, uint8_t data);
+ // device_execute_interface overrides (TODO: /8 in M50740A/41/52/57/58 SLW mode)
+ virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
+ virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ TIMER_CALLBACK_MEMBER(timer1_tick);
+ TIMER_CALLBACK_MEMBER(timer2_tick);
+ TIMER_CALLBACK_MEMBER(timerx_tick);
+ virtual TIMER_CALLBACK_MEMBER(adc_complete) { }
+
+ void send_port(uint8_t offset, uint8_t data);
uint8_t read_port(uint8_t offset);
void recalc_irqs();
void recalc_timer(int timer);
- uint8_t m_ports[6], m_ddrs[6];
+ devcb_read8::array<5> m_read_p;
+ devcb_write8::array<5> m_write_p;
+
+ uint8_t m_ports[5], m_ddrs[5], m_pullups[5];
uint8_t m_intctrl, m_tmrctrl;
uint8_t m_tmr12pre, m_tmr1, m_tmr2, m_tmrxpre, m_tmrx;
uint8_t m_tmr1latch, m_tmr2latch, m_tmrxlatch;
@@ -90,9 +92,11 @@ class m50740_device : public m5074x_device
public:
m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void m50740_map(address_map &map);
protected:
m50740_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ void m50740_map(address_map &map) ATTR_COLD;
};
class m50741_device : public m5074x_device
@@ -100,12 +104,60 @@ class m50741_device : public m5074x_device
public:
m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void m50741_map(address_map &map);
protected:
m50741_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ void m50741_map(address_map &map) ATTR_COLD;
+};
+
+class m50753_device : public m5074x_device
+{
+public:
+ m50753_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ enum
+ {
+ M50753_INT1_LINE = INPUT_LINE_IRQ0,
+ M50753_INT2_LINE = INPUT_LINE_IRQ1
+ };
+
+ template <std::size_t Bit> auto ad_in() { return m_ad_in[Bit].bind(); }
+
+ auto read_in_p() { return m_in_p.bind(); }
+
+protected:
+ m50753_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ virtual TIMER_CALLBACK_MEMBER(adc_complete) override;
+
+private:
+ void m50753_map(address_map &map) ATTR_COLD;
+
+ uint8_t ad_r();
+ uint8_t in_r();
+ void ad_start_w(uint8_t data);
+ uint8_t ad_control_r();
+ void ad_control_w(uint8_t data);
+ void ad_trigger_w(uint8_t data);
+ uint8_t pwm_control_r();
+ void pwm_control_w(uint8_t data);
+
+ devcb_read8::array<8> m_ad_in;
+ devcb_read8 m_in_p;
+
+ uint8_t m_ad_control;
+ bool m_pwm_enabled;
};
DECLARE_DEVICE_TYPE(M50740, m50740_device)
DECLARE_DEVICE_TYPE(M50741, m50741_device)
+DECLARE_DEVICE_TYPE(M50753, m50753_device)
#endif // MAME_CPU_M6502_M5074X_H
diff --git a/src/devices/cpu/m6502/m6500_1.cpp b/src/devices/cpu/m6502/m6500_1.cpp
index cb3630e6668..8aa30f08c89 100644
--- a/src/devices/cpu/m6502/m6500_1.cpp
+++ b/src/devices/cpu/m6502/m6500_1.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Vas Crabb
/***************************************************************************
- m6500_1.h
+ m6500_1.cpp
MOS Technology 6500/1, original NMOS variant with onboard peripherals:
* 6502 CPU
@@ -12,10 +12,10 @@
* Sixteen-bit programmable counter/latch
The onboad clock generator has mask options for an external crystal
- (2MHz to 6MHz) an external TTL-compatible clock with a 300Ω pull-up
+ (2MHz to 6MHz), an external TTL-compatible clock with a 300Ω pull-up
resistor (2MHz to 6MHz), or an RC oscillator with an external 47kΩ
resistor and internal capacitor (nominally 2MHz). The clock is
- divided by two to generate the two-phase CPU code clock.
+ divided by two to generate the two-phase CPU core clock.
There is no on-board power-on reset generator. The /RES pin must be
held low (asserted) for at least eight phase 2 clock cycles after
@@ -45,7 +45,7 @@
on the CNTR pin in event counter mode is half the phase 2 clock
rate. This suggests that an internal flag is set when a rasing edge
is detected on CNTR and reset when the counter is synchronously
- decremented. This is not emulated - for simplicity the counter is
+ decremented. This is not emulated - for simplicity, the counter is
asynchronously decremented on detecting a rising edge on CNTR.
The CNTR pin has an active low driver and internal passive pull-up.
@@ -58,11 +58,23 @@
appear to include the addition of an onboard power-on reset. It
is unknown what other differences these devices have.
+ TODO:
+ - For some reason most if not all Amiga MCU programs access
+ arbitrary zero page 0x90-0xff with a back-to-back cmp($00, x)
+ opcode at PC=c06-c08 with the actual result discarded. X can be
+ any value in the 0x90-0xff range, depending on the last user
+ keypress row source e.g. 0xdf-0xe0 for 'A', 0xef-0xf0 for 'Q',
+ 0xfb-0xfc for function keys.
+ This can be extremely verbose in the logging facility so we nop it
+ out for the time being.
+
***************************************************************************/
#include "emu.h"
#include "m6500_1.h"
+#include "m6502mcu.ipp"
+
namespace {
@@ -78,13 +90,13 @@ constexpr u8 CR_CTRO = 0x80U;
} // anonymous namespace
-DEFINE_DEVICE_TYPE(M6500_1, m6500_1_device, "m6500_1", "MOS M6500/1");
+DEFINE_DEVICE_TYPE(M6500_1, m6500_1_device, "m6500_1", "MOS Technology 6500/1");
m6500_1_device::m6500_1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
- : m6502_mcu_device(mconfig, M6500_1, tag, owner, clock)
- , m_port_in_cb{ { *this }, { *this }, { *this }, { *this } }
- , m_port_out_cb{ { *this }, { *this }, { *this }, { *this } }
+ : m6502_mcu_device_base<m6502_device>(mconfig, M6500_1, tag, owner, clock)
+ , m_port_in_cb{ *this, 0xffU }
+ , m_port_out_cb{ *this }
, m_cntr_out_cb{ *this }
, m_cr{ 0x00U }
, m_port_in{ 0xffU, 0xffU, 0xffU, 0xffU }
@@ -103,49 +115,36 @@ m6500_1_device::m6500_1_device(machine_config const &mconfig, char const *tag, d
}
-WRITE8_MEMBER(m6500_1_device::pa_w)
+void m6500_1_device::pa_w(uint8_t data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<0>), this), unsigned(data));
}
-WRITE8_MEMBER(m6500_1_device::pb_w)
+void m6500_1_device::pb_w(u8 data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<1>), this), unsigned(data));
}
-WRITE8_MEMBER(m6500_1_device::pc_w)
+void m6500_1_device::pc_w(u8 data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<2>), this), unsigned(data));
}
-WRITE8_MEMBER(m6500_1_device::pd_w)
+void m6500_1_device::pd_w(u8 data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<3>), this), unsigned(data));
}
-WRITE_LINE_MEMBER(m6500_1_device::cntr_w)
+void m6500_1_device::cntr_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_cntr_in), this), state);
}
-void m6500_1_device::device_resolve_objects()
-{
- m6502_mcu_device::device_resolve_objects();
-
- for (devcb_read8 &cb : m_port_in_cb)
- cb.resolve();
-
- for (devcb_write8 &cb : m_port_out_cb)
- cb.resolve_safe();
-
- m_cntr_out_cb.resolve_safe();
-}
-
void m6500_1_device::device_start()
{
- m6502_mcu_device::device_start();
+ m6502_mcu_device_base<m6502_device>::device_start();
m_counter_base = 0U;
@@ -167,7 +166,7 @@ void m6500_1_device::device_start()
void m6500_1_device::device_reset()
{
- m6502_mcu_device::device_reset();
+ m6502_mcu_device_base<m6502_device>::device_reset();
SP = 0x003fU;
@@ -175,7 +174,7 @@ void m6500_1_device::device_reset()
m_cr = 0x00U;
- for (unsigned i = 0; ARRAY_LENGTH(m_port_buf) > i; ++i)
+ for (unsigned i = 0; std::size(m_port_buf) > i; ++i)
{
if (0xffU != m_port_buf[i])
m_port_out_cb[i](m_port_buf[i] = 0xffU);
@@ -189,12 +188,12 @@ void m6500_1_device::device_reset()
}
-u64 m6500_1_device::execute_clocks_to_cycles(u64 clocks) const
+u64 m6500_1_device::execute_clocks_to_cycles(u64 clocks) const noexcept
{
return (clocks + 1) / 2;
}
-u64 m6500_1_device::execute_cycles_to_clocks(u64 cycles) const
+u64 m6500_1_device::execute_cycles_to_clocks(u64 cycles) const noexcept
{
return cycles * 2;
}
@@ -232,7 +231,7 @@ void m6500_1_device::state_import(device_state_entry const &entry)
break;
default:
- m6502_mcu_device::state_import(entry);
+ m6502_mcu_device_base<m6502_device>::state_import(entry);
}
}
@@ -263,7 +262,7 @@ void m6500_1_device::state_export(device_state_entry const &entry)
break;
default:
- m6502_mcu_device::state_export(entry);
+ m6502_mcu_device_base<m6502_device>::state_export(entry);
}
}
@@ -276,13 +275,13 @@ void m6500_1_device::internal_update(u64 current_time)
}
-READ8_MEMBER(m6500_1_device::read_control_register)
+u8 m6500_1_device::read_control_register()
{
internal_update();
return m_cr;
}
-WRITE8_MEMBER(m6500_1_device::write_control_register)
+void m6500_1_device::write_control_register(u8 data)
{
internal_update();
m_cr = (m_cr & (CR_A1ED | CR_A0ED | CR_CTRO)) | (data & (CR_CMC0 | CR_CMC1 | CR_A1IE | CR_A0IE | CR_CIE));
@@ -298,12 +297,12 @@ void m6500_1_device::update_irq()
}
-READ8_MEMBER(m6500_1_device::read_port)
+u8 m6500_1_device::read_port(offs_t offset)
{
- if (!machine().side_effects_disabled() && m_port_in_cb[offset])
+ if (!machine().side_effects_disabled() && !m_port_in_cb[offset].isunset())
{
u8 const prev(m_port_in[offset]);
- m_port_in[offset] = m_port_in_cb[offset](space);
+ m_port_in[offset] = m_port_in_cb[offset]();
if (!offset)
{
u8 const diff((prev ^ m_port_in[0]) & m_port_buf[0]);
@@ -318,16 +317,16 @@ READ8_MEMBER(m6500_1_device::read_port)
return m_port_in[offset] & m_port_buf[offset];
}
-WRITE8_MEMBER(m6500_1_device::write_port)
+void m6500_1_device::write_port(offs_t offset, u8 data)
{
u8 const prev(m_port_in[offset] & m_port_buf[offset]);
if (m_port_buf[offset] != data)
- m_port_out_cb[offset](space, m_port_buf[offset] = data);
+ m_port_out_cb[offset](m_port_buf[offset] = data);
if (!offset)
{
- if (!machine().side_effects_disabled() && m_port_in_cb[0])
- m_port_in[0] = m_port_in_cb[0](space);
+ if (!machine().side_effects_disabled() && !m_port_in_cb[0].isunset())
+ m_port_in[0] = m_port_in_cb[0]();
u8 const effective(m_port_in[0] & data);
u8 const diff(prev ^ effective);
if (BIT(diff, 0) && BIT(effective, 0))
@@ -338,7 +337,7 @@ WRITE8_MEMBER(m6500_1_device::write_port)
}
}
-WRITE8_MEMBER(m6500_1_device::clear_edge)
+void m6500_1_device::clear_edge(offs_t offset, u8 data)
{
m_cr &= BIT(offset, 0) ? ~CR_A1ED : ~CR_A0ED;
update_irq();
@@ -347,7 +346,7 @@ WRITE8_MEMBER(m6500_1_device::clear_edge)
template <unsigned Port> TIMER_CALLBACK_MEMBER(m6500_1_device::set_port_in)
{
u8 const prev(m_port_in[Port]);
- m_port_in[Port] = m_port_in_cb[Port] ? m_port_in_cb[Port]() : u8(u32(param));
+ m_port_in[Port] = !m_port_in_cb[Port].isunset() ? m_port_in_cb[Port]() : u8(u32(param));
if (!Port)
{
@@ -361,13 +360,13 @@ template <unsigned Port> TIMER_CALLBACK_MEMBER(m6500_1_device::set_port_in)
}
-READ8_MEMBER(m6500_1_device::read_upper_count)
+u8 m6500_1_device::read_upper_count()
{
internal_update();
return u8(m_counter >> 8);
}
-READ8_MEMBER(m6500_1_device::read_lower_count)
+u8 m6500_1_device::read_lower_count()
{
internal_update();
if (!machine().side_effects_disabled())
@@ -379,7 +378,7 @@ READ8_MEMBER(m6500_1_device::read_lower_count)
return u8(m_counter);
}
-template <bool Transfer> WRITE8_MEMBER(m6500_1_device::write_upper_latch)
+template <bool Transfer> void m6500_1_device::write_upper_latch(u8 data)
{
m_latch = (m_latch & 0x00ffU) | u16(data << 8);
if (Transfer)
@@ -393,7 +392,7 @@ template <bool Transfer> WRITE8_MEMBER(m6500_1_device::write_upper_latch)
}
}
-WRITE8_MEMBER(m6500_1_device::write_lower_latch)
+void m6500_1_device::write_lower_latch(u8 data)
{
m_latch = (m_latch & 0xff00U) | u16(data);
}
@@ -508,5 +507,8 @@ void m6500_1_device::memory_map(address_map &map)
map(0x008f, 0x008f).rw(FUNC(m6500_1_device::read_control_register), FUNC(m6500_1_device::write_control_register));
+ // TODO: mirror or actually unmapped?
+ map(0x0090, 0x00ff).nopr();
+
map(0x0800, 0x0fff).rom().region(DEVICE_SELF, 0);
}
diff --git a/src/devices/cpu/m6502/m6500_1.h b/src/devices/cpu/m6502/m6500_1.h
index 5b48d358b77..0736e927ae5 100644
--- a/src/devices/cpu/m6502/m6500_1.h
+++ b/src/devices/cpu/m6502/m6500_1.h
@@ -39,9 +39,9 @@
#pragma once
-#include "m6502.h"
+#include "m6502mcu.h"
-class m6500_1_device : public m6502_mcu_device
+class m6500_1_device : public m6502_mcu_device_base<m6502_device>
{
public:
m6500_1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
@@ -56,16 +56,16 @@ public:
auto pd_out_cb() { return m_port_out_cb[3].bind(); }
auto cntr_out_cb() { return m_cntr_out_cb.bind(); }
- DECLARE_READ8_MEMBER(pa_r) { return m_port_buf[0]; }
- DECLARE_READ8_MEMBER(pb_r) { return m_port_buf[1]; }
- DECLARE_READ8_MEMBER(pc_r) { return m_port_buf[2]; }
- DECLARE_READ8_MEMBER(pd_r) { return m_port_buf[3]; }
- DECLARE_WRITE8_MEMBER(pa_w);
- DECLARE_WRITE8_MEMBER(pb_w);
- DECLARE_WRITE8_MEMBER(pc_w);
- DECLARE_WRITE8_MEMBER(pd_w);
+ u8 pa_r() { return m_port_buf[0]; }
+ u8 pb_r() { return m_port_buf[1]; }
+ u8 pc_r() { return m_port_buf[2]; }
+ u8 pd_r() { return m_port_buf[3]; }
+ void pa_w(u8 data);
+ void pb_w(u8 data);
+ void pc_w(u8 data);
+ void pd_w(u8 data);
- DECLARE_WRITE_LINE_MEMBER(cntr_w);
+ void cntr_w(int state);
protected:
enum
@@ -77,32 +77,31 @@ protected:
M6500_1_LC
};
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual u64 execute_clocks_to_cycles(u64 clocks) const override;
- virtual u64 execute_cycles_to_clocks(u64 cycles) const override;
+ virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override;
+ virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override;
virtual void state_import(device_state_entry const &entry) override;
virtual void state_export(device_state_entry const &entry) override;
virtual void internal_update(u64 current_time) override;
- using m6502_mcu_device::internal_update;
+ using m6502_mcu_device_base<m6502_device>::internal_update;
- DECLARE_READ8_MEMBER(read_control_register);
- DECLARE_WRITE8_MEMBER(write_control_register);
+ u8 read_control_register();
+ void write_control_register(u8 data);
void update_irq();
- DECLARE_READ8_MEMBER(read_port);
- DECLARE_WRITE8_MEMBER(write_port);
- DECLARE_WRITE8_MEMBER(clear_edge);
+ u8 read_port(offs_t offset);
+ void write_port(offs_t offset, u8 data);
+ void clear_edge(offs_t offset, u8 data);
template <unsigned Port> TIMER_CALLBACK_MEMBER(set_port_in);
- DECLARE_READ8_MEMBER(read_upper_count);
- DECLARE_READ8_MEMBER(read_lower_count);
- template <bool Transfer> DECLARE_WRITE8_MEMBER(write_upper_latch);
- DECLARE_WRITE8_MEMBER(write_lower_latch);
+ u8 read_upper_count();
+ u8 read_lower_count();
+ template <bool Transfer> void write_upper_latch(u8 data);
+ void write_lower_latch(u8 data);
u64 update_counter(u64 current_time);
bool should_count() const;
bool pulse_generator_mode() const;
@@ -110,12 +109,12 @@ protected:
TIMER_CALLBACK_MEMBER(set_cntr_in);
void toggle_cntr();
- void memory_map(address_map &map);
+ void memory_map(address_map &map) ATTR_COLD;
private:
- devcb_read8 m_port_in_cb[4];
- devcb_write8 m_port_out_cb[4];
- devcb_write_line m_cntr_out_cb;
+ devcb_read8::array<4> m_port_in_cb;
+ devcb_write8::array<4> m_port_out_cb;
+ devcb_write_line m_cntr_out_cb;
u8 m_cr;
diff --git a/src/devices/cpu/m6502/m6502.cpp b/src/devices/cpu/m6502/m6502.cpp
index 013e4f19ef4..e72fd74459a 100644
--- a/src/devices/cpu/m6502/m6502.cpp
+++ b/src/devices/cpu/m6502/m6502.cpp
@@ -2,59 +2,62 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6502.c
+ m6502.cpp
MOS Technology 6502, original NMOS variant
***************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "m6502.h"
#include "m6502d.h"
-DEFINE_DEVICE_TYPE(M6502, m6502_device, "m6502", "MOS Technology M6502")
+DEFINE_DEVICE_TYPE(M6502, m6502_device, "m6502", "MOS Technology 6502")
+DEFINE_DEVICE_TYPE(M6512, m6512_device, "m6512", "MOS Technology 6512")
m6502_device::m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, M6502, tag, owner, clock)
{
}
+m6512_device::m6512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, M6512, tag, owner, clock)
+{
+}
+
m6502_device::m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
cpu_device(mconfig, type, tag, owner, clock),
sync_w(*this),
program_config("program", ENDIANNESS_LITTLE, 8, 16),
- sprogram_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16), PPC(0), NPC(0), PC(0), SP(0), TMP(0), TMP2(0), A(0), X(0), Y(0), P(0), IR(0), inst_state_base(0), mintf(nullptr),
- inst_state(0), inst_substate(0), icount(0), nmi_state(false), irq_state(false), apu_irq_state(false), v_state(false), irq_taken(false), sync(false), inhibit_interrupts(false)
+ sprogram_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16),
+ mintf(nullptr),
+ uses_custom_memory_interface(false)
{
- cache_disabled = false;
}
void m6502_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_default_nd>();
- else
- mintf = std::make_unique<mi_default_normal>();
+ if(!uses_custom_memory_interface)
+ mintf = space(AS_PROGRAM).addr_width() > 14 ? std::make_unique<mi_default>() : std::make_unique<mi_default14>();
init();
}
void m6502_device::init()
{
- mintf->program = &space(AS_PROGRAM);
- mintf->sprogram = has_space(AS_OPCODES) ? &space(AS_OPCODES) : mintf->program;
+ if(mintf) {
+ space(AS_PROGRAM).cache(mintf->cprogram);
+ space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).cache(mintf->csprogram);
- mintf->cache = mintf->program->cache<0, 0, ENDIANNESS_LITTLE>();
- mintf->scache = mintf->sprogram->cache<0, 0, ENDIANNESS_LITTLE>();
-
- sync_w.resolve_safe();
-
- XPC = 0;
+ // specific group 1-14 or 15-31
+ if(space(AS_PROGRAM).addr_width() > 14)
+ space(AS_PROGRAM).specific(mintf->program);
+ else
+ space(AS_PROGRAM).specific(mintf->program14);
+ }
state_add(STATE_GENPC, "GENPC", XPC).callexport().noshow();
state_add(STATE_GENPCBASE, "CURPC", XPC).callexport().noshow();
- state_add(STATE_GENSP, "GENSP", SP).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", P).callimport().formatstr("%6s").noshow();
state_add(M6502_PC, "PC", NPC).callimport();
state_add(M6502_A, "A", A);
@@ -79,14 +82,17 @@ void m6502_device::init()
save_item(NAME(irq_state));
save_item(NAME(apu_irq_state));
save_item(NAME(v_state));
+ save_item(NAME(nmi_pending));
+ save_item(NAME(irq_taken));
save_item(NAME(inst_state));
save_item(NAME(inst_substate));
save_item(NAME(inst_state_base));
- save_item(NAME(irq_taken));
save_item(NAME(inhibit_interrupts));
set_icountptr(icount);
+ XPC = 0x0000;
+ PPC = 0x0000;
PC = 0x0000;
NPC = 0x0000;
A = 0x00;
@@ -100,8 +106,9 @@ void m6502_device::init()
nmi_state = false;
irq_state = false;
apu_irq_state = false;
- irq_taken = false;
v_state = false;
+ nmi_pending = false;
+ irq_taken = false;
inst_state = STATE_RESET;
inst_substate = 0;
inst_state_base = 0;
@@ -115,35 +122,27 @@ void m6502_device::device_reset()
inst_state = STATE_RESET;
inst_substate = 0;
inst_state_base = 0;
- nmi_state = false;
- irq_state = false;
- apu_irq_state = false;
+ nmi_pending = false;
irq_taken = false;
- v_state = false;
sync = false;
sync_w(CLEAR_LINE);
inhibit_interrupts = false;
}
-uint32_t m6502_device::execute_min_cycles() const
+uint32_t m6502_device::execute_min_cycles() const noexcept
{
return 1;
}
-uint32_t m6502_device::execute_max_cycles() const
+uint32_t m6502_device::execute_max_cycles() const noexcept
{
return 10;
}
-uint32_t m6502_device::execute_input_lines() const
+bool m6502_device::execute_input_edge_triggered(int inputnum) const noexcept
{
- return NMI_LINE+1;
-}
-
-bool m6502_device::execute_input_edge_triggered(int inputnum) const
-{
- return inputnum == NMI_LINE;
+ return inputnum == NMI_LINE || inputnum == V_LINE;
}
void m6502_device::do_adc_d(uint8_t val)
@@ -395,7 +394,7 @@ void m6502_device::execute_run()
if(inst_state < 0xff00) {
PPC = NPC;
inst_state = IR | inst_state_base;
- if(machine().debug_flags & DEBUG_FLAG_ENABLED)
+ if(debugger_enabled())
debugger_instruction_hook(pc_to_external(NPC));
}
do_exec_full();
@@ -407,9 +406,13 @@ void m6502_device::execute_set_input(int inputnum, int state)
switch(inputnum) {
case IRQ_LINE: irq_state = state == ASSERT_LINE; break;
case APU_IRQ_LINE: apu_irq_state = state == ASSERT_LINE; break;
- case NMI_LINE: nmi_state = nmi_state || (state == ASSERT_LINE); break;
+ case NMI_LINE:
+ if(machine().time() > attotime::zero && !nmi_state && state == ASSERT_LINE)
+ nmi_pending = true;
+ nmi_state = state == ASSERT_LINE;
+ break;
case V_LINE:
- if(!v_state && state == ASSERT_LINE)
+ if(machine().time() > attotime::zero && !v_state && state == ASSERT_LINE)
P |= F_V;
v_state = state == ASSERT_LINE;
break;
@@ -441,7 +444,9 @@ void m6502_device::state_import(const device_state_entry &entry)
case M6502_PC:
PC = NPC;
irq_taken = false;
- prefetch();
+ prefetch_start();
+ IR = mintf->read_sync(PC);
+ prefetch_end();
PPC = NPC;
inst_state = IR | inst_state_base;
break;
@@ -472,30 +477,32 @@ void m6502_device::state_string_export(const device_state_entry &entry, std::str
}
}
-void m6502_device::prefetch()
+void m6502_device::prefetch_start()
{
sync = true;
- sync_w(ASSERT_LINE);
+ if(!sync_w.isunset())
+ sync_w(ASSERT_LINE);
NPC = PC;
- IR = mintf->read_sync(PC);
+}
+
+void m6502_device::prefetch_end()
+{
sync = false;
- sync_w(CLEAR_LINE);
+ if(!sync_w.isunset())
+ sync_w(CLEAR_LINE);
- if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) {
+ if((nmi_pending || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) {
irq_taken = true;
IR = 0x00;
} else
PC++;
}
-void m6502_device::prefetch_noirq()
+void m6502_device::prefetch_end_noirq()
{
- sync = true;
- sync_w(ASSERT_LINE);
- NPC = PC;
- IR = mintf->read_sync(PC);
sync = false;
- sync_w(CLEAR_LINE);
+ if(!sync_w.isunset())
+ sync_w(CLEAR_LINE);
PC++;
}
@@ -524,97 +531,34 @@ void m6502_device::memory_interface::write_9(uint16_t adr, uint8_t val)
}
-uint8_t m6502_device::mi_default_normal::read(uint16_t adr)
+uint8_t m6502_device::mi_default::read(uint16_t adr)
{
- return program->read_byte(adr);
+ return program.read_byte(adr);
}
-uint8_t m6502_device::mi_default_normal::read_sync(uint16_t adr)
+uint8_t m6502_device::mi_default::read_sync(uint16_t adr)
{
- return scache->read_byte(adr);
+ return csprogram.read_byte(adr);
}
-uint8_t m6502_device::mi_default_normal::read_arg(uint16_t adr)
+uint8_t m6502_device::mi_default::read_arg(uint16_t adr)
{
- return cache->read_byte(adr);
+ return cprogram.read_byte(adr);
}
-
-void m6502_device::mi_default_normal::write(uint16_t adr, uint8_t val)
-{
- program->write_byte(adr, val);
-}
-
-uint8_t m6502_device::mi_default_nd::read_sync(uint16_t adr)
-{
- return sprogram->read_byte(adr);
-}
-
-uint8_t m6502_device::mi_default_nd::read_arg(uint16_t adr)
+void m6502_device::mi_default::write(uint16_t adr, uint8_t val)
{
- return program->read_byte(adr);
+ program.write_byte(adr, val);
}
-m6502_mcu_device::m6502_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m6502_device(mconfig, type, tag, owner, clock)
+uint8_t m6502_device::mi_default14::read(uint16_t adr)
{
+ return program14.read_byte(adr);
}
-
-void m6502_mcu_device::recompute_bcount(uint64_t event_time)
-{
- if(!event_time || event_time >= total_cycles() + icount) {
- bcount = 0;
- return;
- }
- bcount = total_cycles() + icount - event_time;
-}
-
-void m6502_mcu_device::execute_run()
-{
- internal_update(total_cycles());
-
- icount -= count_before_instruction_step;
- if(icount < 0) {
- count_before_instruction_step = -icount;
- icount = 0;
- } else
- count_before_instruction_step = 0;
-
- while(bcount && icount <= bcount)
- internal_update(total_cycles() + icount - bcount);
-
- if(icount > 0 && inst_substate)
- do_exec_partial();
-
- while(icount > 0) {
- while(icount > bcount) {
- if(inst_state < 0xff00) {
- PPC = NPC;
- inst_state = IR | inst_state_base;
- if(machine().debug_flags & DEBUG_FLAG_ENABLED)
- debugger_instruction_hook(NPC);
- }
- do_exec_full();
- }
- if(icount > 0)
- while(bcount && icount <= bcount)
- internal_update(total_cycles() + icount - bcount);
- if(icount > 0 && inst_substate)
- do_exec_partial();
- }
- if(icount < 0) {
- count_before_instruction_step = -icount;
- icount = 0;
- }
-}
-
-void m6502_mcu_device::add_event(uint64_t &event_time, uint64_t new_event)
+void m6502_device::mi_default14::write(uint16_t adr, uint8_t val)
{
- if(!new_event)
- return;
- if(!event_time || event_time > new_event)
- event_time = new_event;
+ program14.write_byte(adr, val);
}
diff --git a/src/devices/cpu/m6502/m6502.h b/src/devices/cpu/m6502/m6502.h
index b6034d98f0a..112630dfd50 100644
--- a/src/devices/cpu/m6502/m6502.h
+++ b/src/devices/cpu/m6502/m6502.h
@@ -11,6 +11,9 @@
#ifndef MAME_CPU_M6502_M6502_H
#define MAME_CPU_M6502_M6502_H
+#pragma once
+
+
class m6502_device : public cpu_device {
public:
enum {
@@ -20,24 +23,13 @@ public:
V_LINE = INPUT_LINE_IRQ0 + 16
};
- m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- bool get_sync() const { return sync; }
- void disable_cache() { cache_disabled = true; }
-
- auto sync_cb() { return sync_w.bind(); }
-
- devcb_write_line sync_w;
-
-protected:
- m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
class memory_interface {
public:
- address_space *program, *sprogram;
- memory_access_cache<0, 0, ENDIANNESS_LITTLE> *cache, *scache;
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache cprogram, csprogram;
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific program;
+ memory_access<14, 0, 0, ENDIANNESS_LITTLE>::specific program14;
- virtual ~memory_interface() {}
+ virtual ~memory_interface() = default;
virtual uint8_t read(uint16_t adr) = 0;
virtual uint8_t read_9(uint16_t adr);
virtual uint8_t read_sync(uint16_t adr) = 0;
@@ -46,20 +38,41 @@ protected:
virtual void write_9(uint16_t adr, uint8_t val);
};
- class mi_default_normal : public memory_interface {
+ m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void set_address_width(int width, bool custom_interface) {
+ program_config.m_addr_width = width;
+ sprogram_config.m_addr_width = width;
+ uses_custom_memory_interface = custom_interface;
+ }
+
+ void set_custom_memory_interface(std::unique_ptr<memory_interface> interface) {
+ mintf = std::move(interface);
+ }
+
+ bool get_sync() const { return sync; }
+
+ auto sync_cb() { return sync_w.bind(); }
+
+ devcb_write_line sync_w;
+
+protected:
+ m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ class mi_default : public memory_interface {
public:
- virtual ~mi_default_normal() {}
+ virtual ~mi_default() = default;
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
virtual uint8_t read_arg(uint16_t adr) override;
virtual void write(uint16_t adr, uint8_t val) override;
};
- class mi_default_nd : public mi_default_normal {
+ class mi_default14 : public mi_default {
public:
- virtual ~mi_default_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
+ virtual ~mi_default14() = default;
+ virtual uint8_t read(uint16_t adr) override;
+ virtual void write(uint16_t adr, uint8_t val) override;
};
enum {
@@ -81,16 +94,16 @@ protected:
virtual void init();
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override;
- virtual uint32_t execute_max_cycles() const override;
- virtual uint32_t execute_input_lines() const override;
+ virtual bool cpu_is_interruptible() const override { return true; }
+ virtual uint32_t execute_min_cycles() const noexcept override;
+ virtual uint32_t execute_max_cycles() const noexcept override;
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
- virtual bool execute_input_edge_triggered(int inputnum) const override;
+ virtual bool execute_input_edge_triggered(int inputnum) const noexcept override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
@@ -116,23 +129,24 @@ protected:
uint8_t Y; /* Y index register */
uint8_t P; /* Processor status */
uint8_t IR; /* Prefetched instruction register */
- int inst_state_base; /* Current instruction bank */
+ int inst_state_base; /* Current instruction bank */
std::unique_ptr<memory_interface> mintf;
int inst_state, inst_substate;
int icount, bcount, count_before_instruction_step;
bool nmi_state, irq_state, apu_irq_state, v_state;
- bool irq_taken, sync, cache_disabled, inhibit_interrupts;
+ bool nmi_pending, irq_taken, sync, inhibit_interrupts;
+ bool uses_custom_memory_interface;
uint8_t read(uint16_t adr) { return mintf->read(adr); }
uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); }
void write(uint16_t adr, uint8_t val) { mintf->write(adr, val); }
void write_9(uint16_t adr, uint8_t val) { mintf->write_9(adr, val); }
uint8_t read_arg(uint16_t adr) { return mintf->read_arg(adr); }
- uint8_t read_pc() { return mintf->read_arg(PC++); }
- uint8_t read_pc_noinc() { return mintf->read_arg(PC); }
- void prefetch();
- void prefetch_noirq();
+ uint8_t read_pc() { return mintf->read_arg(PC); }
+ void prefetch_start();
+ void prefetch_end();
+ void prefetch_end_noirq();
void set_nz(uint8_t v);
u32 XPC;
@@ -265,16 +279,9 @@ protected:
#undef O
};
-class m6502_mcu_device : public m6502_device {
-protected:
- m6502_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- void internal_update() { internal_update(total_cycles()); }
- virtual void internal_update(uint64_t current_time) = 0;
- void recompute_bcount(uint64_t event_time);
- static void add_event(uint64_t &event_time, uint64_t new_event);
-
- virtual void execute_run() override;
+class m6512_device : public m6502_device {
+public:
+ m6512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
enum {
@@ -294,5 +301,6 @@ enum {
};
DECLARE_DEVICE_TYPE(M6502, m6502_device)
+DECLARE_DEVICE_TYPE(M6512, m6512_device)
#endif // MAME_CPU_M6502_M6502_H
diff --git a/src/devices/cpu/m6502/m6502.txt b/src/devices/cpu/m6502/m6502.txt
index d92af7ec146..2d4564ee0be 100644
--- a/src/devices/cpu/m6502/m6502.txt
+++ b/src/devices/cpu/m6502/m6502.txt
@@ -25,9 +25,15 @@ timer
b-flag always 1! (only pushed as 0 when break executed!)
memory changing opcodes accesses memory: read, write data, write modified data
-6504
+6503
only 12 address pins a11..a0
+6504
+only 13 address pins a12..a0
+
+6507
+only 13 address pins a12..a0
+
6508
8 io pins (p0 bis p7)
@@ -52,7 +58,7 @@ no nmi
the above series is opcode compatible (including illegal opcodes)
-n2a03 (some arcades, NES)
+rp2a03 (some arcades, NES)
-------------------------
(nintendo variant)
NMOS based!
@@ -80,11 +86,11 @@ several other CMOS variants
additional commands
atari lynx bastian schicks bll
-integrated m65sc02 cpu core
-no bbr bbs instructions, else m65c02 compatible
+integrated g65sc02 cpu core
+no bbr bbs instructions, else w65c02 compatible
watara supervision
-integrated m65c02 cpu core (or m65sc02 or m65ce02?)
+integrated w65c02 cpu core (or g65sc02 or m65ce02?)
gte65816 (nintendo snes)
@@ -159,5 +165,5 @@ MUL, DIV not in all variants
Set Overflow Pin
----------------
in 6502 and pin compatibles (65C02 65SC02 65SC802 65CE02), M6509
-no SO pin 6510/7501/8500/8501/8502/65sc816
+no SO pin 6503/6504/6507/6510/7501/8500/8501/8502/65sc816
6510T ?
diff --git a/src/devices/cpu/m6502/m6502d.cpp b/src/devices/cpu/m6502/m6502d.cpp
index 589aafdf3b7..f299f77cfc6 100644
--- a/src/devices/cpu/m6502/m6502d.cpp
+++ b/src/devices/cpu/m6502/m6502d.cpp
@@ -62,6 +62,11 @@ offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
flags |= 3;
break;
+ case DASM_amr:
+ util::stream_format(stream, " $%02x%02x, #$%02x, $%04x", params.r8(pc+2), params.r8(pc+1), params.r8(pc+3), uint16_t(pc + 5 + int8_t(params.r8(pc+4))));
+ flags |= 5;
+ break;
+
case DASM_bzp:
util::stream_format(stream, "%d $%02x", (opcodes.r8(pc) >> 4) & 7, params.r8(pc+1));
flags |= 2;
@@ -87,6 +92,11 @@ offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
flags |= 2;
break;
+ case DASM_ima:
+ util::stream_format(stream, " #$%02x, $%02x%02x", params.r8(pc+1), params.r8(pc+3), params.r8(pc+2));
+ flags |= 4;
+ break;
+
case DASM_imm:
util::stream_format(stream, " #$%02x", params.r8(pc+1));
flags |= 2;
@@ -101,6 +111,11 @@ offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
flags |= 3;
break;
+ case DASM_ipx:
+ util::stream_format(stream, " ($%02x), x", params.r8(pc+1));
+ flags |= 2;
+ break;
+
case DASM_isy:
util::stream_format(stream, " ($%02x, s), y", params.r8(pc+1));
flags |= 2;
@@ -126,6 +141,11 @@ offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
flags |= 3;
break;
+ case DASM_vec:
+ util::stream_format(stream, "%d", (opcodes.r8(pc) >> 4) & 7);
+ flags |= 1;
+ break;
+
case DASM_zpb:
util::stream_format(stream, "%d $%02x, $%04x", (opcodes.r8(pc) >> 4) & 7, params.r8(pc+1), (pc & 0xf0000) | uint16_t(pc + 3 + int8_t(params.r8(pc+2))));
flags |= 3;
@@ -172,7 +192,7 @@ offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
break;
case DASM_bar:
- util::stream_format(stream, " %d, a, $%04x", (opcodes.r8(pc) >> 5) & 7, (pc & 0xf0000) | uint16_t(pc + 3 + int8_t(params.r8(pc+1))));
+ util::stream_format(stream, " %d, a, $%04x", (opcodes.r8(pc) >> 5) & 7, (pc & 0xf0000) | uint16_t(pc + 2 + int8_t(params.r8(pc+1))));
flags |= 2;
break;
diff --git a/src/devices/cpu/m6502/m6502d.h b/src/devices/cpu/m6502/m6502d.h
index 5a02dddca04..d975afab7c7 100644
--- a/src/devices/cpu/m6502/m6502d.h
+++ b/src/devices/cpu/m6502/m6502d.h
@@ -36,19 +36,23 @@ protected:
DASM_aby, /* absolute + Y */
DASM_acc, /* accumulator */
DASM_adr, /* absolute address (jmp,jsr) */
+ DASM_amr, /* absolute address, mask byte and relative address (r65c19) */
DASM_bzp, /* zero page with bit selection */
DASM_iax, /* indirect + X (65c02 jmp) */
DASM_idx, /* zero page pre indexed */
DASM_idy, /* zero page post indexed */
DASM_idz, /* zero page post indexed (65ce02) */
+ DASM_ima, /* immediate byte and absolute address (r65c19) */
DASM_imm, /* immediate */
DASM_imp, /* implicit */
DASM_ind, /* indirect (jmp) */
+ DASM_ipx, /* zero page post indexed (r65c19) */
DASM_isy, /* zero page pre indexed sp and post indexed Y (65ce02) */
DASM_iw2, /* immediate word (65ce02) */
DASM_iw3, /* augment (65ce02) */
DASM_rel, /* relative */
DASM_rw2, /* relative word (65cs02, 65ce02) */
+ DASM_vec, /* vector (r65c19 jbs) */
DASM_zpb, /* zero page and branch (65c02 bbr, bbs) */
DASM_zpg, /* zero page */
DASM_zpi, /* zero page indirect (65c02) */
diff --git a/src/devices/cpu/m6502/m6502make.py b/src/devices/cpu/m6502/m6502make.py
index ea51fe43350..99b4320cc11 100755
--- a/src/devices/cpu/m6502/m6502make.py
+++ b/src/devices/cpu/m6502/m6502make.py
@@ -4,13 +4,14 @@
from __future__ import print_function
+import io
+import logging
+import sys
+
USAGE = """
Usage:
%s prefix {opc.lst|-} disp.lst device.inc deviced.inc
"""
-import sys
-import logging
-
MAX_STATES = 0
def load_opcodes(fname):
@@ -18,7 +19,7 @@ def load_opcodes(fname):
opcodes = []
logging.info("load_opcodes: %s", fname)
try:
- f = open(fname, "rU")
+ f = io.open(fname, "r")
except Exception:
err = sys.exc_info()[1]
logging.error("cannot read opcodes file %s [%s]", fname, err)
@@ -30,7 +31,16 @@ def load_opcodes(fname):
if not line: continue
if line.startswith(" ") or line.startswith("\t"):
# append instruction to last opcode
- opcodes[-1][1].append(line)
+ if line == '\tprefetch();':
+ opcodes[-1][1].append("\tprefetch_start();")
+ opcodes[-1][1].append("\tIR = mintf->read_sync(PC);")
+ opcodes[-1][1].append("\tprefetch_end();")
+ elif line == '\tprefetch_noirq();':
+ opcodes[-1][1].append("\tprefetch_start();")
+ opcodes[-1][1].append("\tIR = mintf->read_sync(PC);")
+ opcodes[-1][1].append("\tprefetch_end_noirq();")
+ else:
+ opcodes[-1][1].append(line)
else:
# add new opcode
opcodes.append((line, []))
@@ -41,7 +51,7 @@ def load_disp(fname):
logging.info("load_disp: %s", fname)
states = []
try:
- f = open(fname, "rU")
+ f = io.open(fname, "r")
except Exception:
err = sys.exc_info()[1]
logging.error("cannot read display file %s [%s]", fname, err)
@@ -58,61 +68,10 @@ def emit(f, text):
"""write string to file"""
print(text, file=f)
-FULL_PROLOG="""\
-void %(device)s_device::%(opcode)s_full()
-{
-"""
-FULL_EPILOG="""\
-}
-"""
-
-FULL_EAT_ALL="""\
-\ticount=0; inst_substate = %(substate)s; return;
-"""
-
-FULL_MEMORY="""\
-\tif(icount == 0) { inst_substate = %(substate)s; return; }
-%(ins)s
-\ticount--;
-"""
-
-FULL_NONE="""\
-%(ins)s
-"""
-
-PARTIAL_PROLOG="""\
-void %(device)s_device::%(opcode)s_partial()
-{
-switch(inst_substate) {
-case 0:
-"""
-
-PARTIAL_EPILOG="""\
-}
-\tinst_substate = 0;
-}
-
-"""
-
-PARTIAL_EAT_ALL="""\
-\ticount=0; inst_substate = %(substate)s; return;
-case %(substate)s:;
-"""
-
-PARTIAL_MEMORY="""\
-\tif(icount == 0) { inst_substate = %(substate)s; return; }
-case %(substate)s:
-%(ins)s
-\ticount--;
-"""
-
-PARTIAL_NONE="""\
-%(ins)s
-"""
def identify_line_type(ins):
if "eat-all-cycles" in ins: return "EAT"
- for s in ["read", "write", "prefetch(", "prefetch_noirq("]:
+ for s in ["read", "write"]:
if s in ins:
return "MEMORY"
return "NONE"
@@ -120,41 +79,71 @@ def identify_line_type(ins):
def save_opcodes(f, device, opcodes):
for name, instructions in opcodes:
- d = { "device": device,
- "opcode": name,
- }
-
- emit(f, FULL_PROLOG % d)
+ emit(f, "void %s_device::%s_full()" % (device, name))
+ emit(f, "{")
substate = 1
for ins in instructions:
- d["substate"] = str(substate)
- d["ins"] = ins
line_type = identify_line_type(ins)
if line_type == "EAT":
- emit(f, FULL_EAT_ALL % d)
+ emit(f, "\tdebugger_wait_hook();")
+ emit(f, "\ticount = 0;")
+ emit(f, "\tinst_substate = %d;" % substate)
+ emit(f, "\treturn;")
substate += 1
elif line_type == "MEMORY":
- emit(f, FULL_MEMORY % d)
- substate += 1
+ emit(f, ins)
+ emit(f, "\ticount--;")
+ emit(f, "\tif(icount <= 0) {")
+ emit(f, "\t\tif(access_to_be_redone()) {")
+ emit(f, "\t\t\ticount++;")
+ emit(f, "\t\t\tinst_substate = %d;" % substate)
+ emit(f, "\t\t} else")
+ emit(f, "\t\t\tinst_substate = %d;" % (substate+1))
+ emit(f, "\t\treturn;")
+ emit(f, "\t}")
+ substate += 2
else:
- emit(f, FULL_NONE %d)
- emit(f, FULL_EPILOG % d)
-
- emit(f, PARTIAL_PROLOG % d)
+ emit(f, ins)
+ emit(f, "}")
+ emit(f, "")
+
+ emit(f, "void %s_device::%s_partial()" % (device, name))
+ emit(f, "{")
+ emit(f, "\tswitch(inst_substate) {")
+ emit(f, "case 0:")
substate = 1
for ins in instructions:
- d["substate"] = str(substate)
- d["ins"] = ins
line_type = identify_line_type(ins)
if line_type == "EAT":
- emit(f, PARTIAL_EAT_ALL % d)
+ emit(f, "\tdebugger_wait_hook();")
+ emit(f, "\ticount = 0;")
+ emit(f, "\tinst_substate = %d;" % substate)
+ emit(f, "\treturn;")
+ emit(f, "\tcase %d:;" % substate)
substate += 1
elif line_type == "MEMORY":
- emit(f, PARTIAL_MEMORY % d)
- substate += 1
+ emit(f, "\t[[fallthrough]];")
+ emit(f, "case %d:" % substate)
+ emit(f, ins)
+ emit(f, "\ticount--;")
+ emit(f, "\tif(icount <= 0) {")
+ emit(f, "\t\tif(access_to_be_redone()) {")
+ emit(f, "\t\t\ticount++;")
+ emit(f, "\t\t\tinst_substate = %d;" % substate)
+ emit(f, "\t\t} else")
+ emit(f, "\t\t\tinst_substate = %d;" % (substate+1))
+ emit(f, "\t\treturn;")
+ emit(f, "\t}")
+ emit(f, "\t[[fallthrough]];")
+ emit(f, "case %d:;" % (substate+1))
+ substate += 2
else:
- emit(f, PARTIAL_NONE %d)
- emit(f, PARTIAL_EPILOG % d)
+ emit(f, ins)
+ emit(f, "\tbreak;")
+ emit(f, "}")
+ emit(f, "\tinst_substate = 0;")
+ emit(f, "}")
+ emit(f, "")
DO_EXEC_FULL_PROLOG="""\
@@ -193,7 +182,7 @@ def save_tables(f, device, states):
d = { "device": device,
"disasm_count": total_states-1
}
-
+
emit(f, DO_EXEC_FULL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
@@ -218,7 +207,7 @@ def save_dasm(f, device, states):
d = { "device": device,
"disasm_count": total_states-1
}
-
+
emit(f, DISASM_PROLOG % d )
for n, state in enumerate(states):
if state == ".": continue
@@ -227,10 +216,12 @@ def save_dasm(f, device, states):
opc = tokens[0]
mode = tokens[-1]
extra = "0"
- if opc in ["jsr", "bsr", "callf"]:
+ if opc in ["jsr", "bsr", "callf", "jpi", "jsb"]:
extra = "STEP_OVER"
- elif opc in ["rts", "rti", "rtn", "retf"]:
+ elif opc in ["rts", "rti", "rtn", "retf", "tpi"]:
extra = "STEP_OUT"
+ elif opc in ["bcc", "bcs", "beq", "bmi", "bne", "bpl", "bvc", "bvs", "bbr", "bbs", "bbc", "bar", "bas"]:
+ extra = "STEP_COND"
emit(f, '\t{ "%s", DASM_%s, %s },' % (opc, mode, extra))
emit(f, DISASM_EPILOG % d)
diff --git a/src/devices/cpu/m6502/m6502mcu.h b/src/devices/cpu/m6502/m6502mcu.h
new file mode 100644
index 00000000000..e126e8fc188
--- /dev/null
+++ b/src/devices/cpu/m6502/m6502mcu.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502mcu.h
+
+ Helper for 6502 variants with internal peripherals
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M6502MCU_H
+#define MAME_CPU_M6502_M6502MCU_H
+
+#pragma once
+
+#include "m6502.h"
+
+
+template <typename Base>
+class m6502_mcu_device_base : public Base {
+protected:
+ m6502_mcu_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void internal_update() { internal_update(this->total_cycles()); }
+ virtual void internal_update(uint64_t current_time) = 0;
+ void recompute_bcount(uint64_t event_time);
+
+ static void add_event(uint64_t &event_time, uint64_t new_event)
+ {
+ if(new_event && (!event_time || event_time > new_event))
+ event_time = new_event;
+ }
+
+ virtual void execute_run() override;
+};
+
+#endif // MAME_CPU_M6502_M6502MCU_H
diff --git a/src/devices/cpu/m6502/m6502mcu.ipp b/src/devices/cpu/m6502/m6502mcu.ipp
new file mode 100644
index 00000000000..d4fd6833f54
--- /dev/null
+++ b/src/devices/cpu/m6502/m6502mcu.ipp
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502mcu.ipp
+
+ Helper for 6502 variants with internal peripherals
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M6502MCU_IPP
+#define MAME_CPU_M6502_M6502MCU_IPP
+
+#pragma once
+
+#include "m6502mcu.h"
+
+
+template <typename Base>
+m6502_mcu_device_base<Base>::m6502_mcu_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ Base(mconfig, type, tag, owner, clock)
+{
+}
+
+
+template <typename Base>
+void m6502_mcu_device_base<Base>::recompute_bcount(uint64_t event_time)
+{
+ if(!event_time || event_time >= this->total_cycles() + this->icount)
+ this->bcount = 0;
+ else
+ this->bcount = this->total_cycles() + this->icount - event_time;
+}
+
+template <typename Base>
+void m6502_mcu_device_base<Base>::execute_run()
+{
+ internal_update(this->total_cycles());
+
+ this->icount -= this->count_before_instruction_step;
+ if(this->icount < 0) {
+ this->count_before_instruction_step = -this->icount;
+ this->icount = 0;
+ } else
+ this->count_before_instruction_step = 0;
+
+ while(this->bcount && this->icount <= this->bcount)
+ internal_update(this->total_cycles() + this->icount - this->bcount);
+
+ if(this->icount > 0 && this->inst_substate)
+ this->do_exec_partial();
+
+ while(this->icount > 0) {
+ while(this->icount > this->bcount) {
+ if(this->inst_state < 0xff00) {
+ this->PPC = this->NPC;
+ this->inst_state = this->IR | this->inst_state_base;
+ if(this->debugger_enabled())
+ this->debugger_instruction_hook(this->NPC);
+ }
+ this->do_exec_full();
+ }
+ if(this->icount > 0)
+ while(this->bcount && this->icount <= this->bcount)
+ internal_update(this->total_cycles() + this->icount - this->bcount);
+ if(this->icount > 0 && this->inst_substate)
+ this->do_exec_partial();
+ }
+ if(this->icount < 0) {
+ this->count_before_instruction_step = -this->icount;
+ this->icount = 0;
+ }
+}
+
+#endif // MAME_CPU_M6502_M6502MCU_IPP
diff --git a/src/devices/cpu/m6502/m6503.cpp b/src/devices/cpu/m6502/m6503.cpp
new file mode 100644
index 00000000000..efaeca3b5a2
--- /dev/null
+++ b/src/devices/cpu/m6502/m6503.cpp
@@ -0,0 +1,25 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6503.cpp
+
+ MOS Technology 6502, NMOS variant with reduced address bus
+
+ 28-pin package, address bus is 12 bits, no NMI, no SO, no SYNC, no RDY.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "m6503.h"
+
+DEFINE_DEVICE_TYPE(M6503, m6503_device, "m6503", "MOS Technology 6503")
+
+m6503_device::m6503_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, M6503, tag, owner, clock)
+{
+ program_config.m_addr_width = 12;
+ program_config.m_logaddr_width = 12;
+ sprogram_config.m_addr_width = 12;
+ sprogram_config.m_logaddr_width = 12;
+}
diff --git a/src/devices/cpu/m6502/m6503.h b/src/devices/cpu/m6502/m6503.h
new file mode 100644
index 00000000000..dadffe3d095
--- /dev/null
+++ b/src/devices/cpu/m6502/m6503.h
@@ -0,0 +1,28 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6503.h
+
+ MOS Technology 6502, NMOS variant with reduced address bus
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M6503_H
+#define MAME_CPU_M6502_M6503_H
+
+#include "m6502.h"
+
+class m6503_device : public m6502_device {
+public:
+ m6503_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+
+enum {
+ M6503_IRQ_LINE = m6502_device::IRQ_LINE
+};
+
+DECLARE_DEVICE_TYPE(M6503, m6503_device);
+
+#endif // MAME_CPU_M6502_M6503_H
diff --git a/src/devices/cpu/m6502/m6504.cpp b/src/devices/cpu/m6502/m6504.cpp
index b2c8132d3ad..3a859621917 100644
--- a/src/devices/cpu/m6502/m6504.cpp
+++ b/src/devices/cpu/m6502/m6504.cpp
@@ -2,60 +2,24 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6504.c
+ m6504.cpp
MOS Technology 6502, NMOS variant with reduced address bus
+ 28-pin package, address bus is 13 bits, no NMI, no SO, no SYNC, no RDY.
+
***************************************************************************/
#include "emu.h"
#include "m6504.h"
-DEFINE_DEVICE_TYPE(M6504, m6504_device, "m6504", "MOS Technology M6504")
+DEFINE_DEVICE_TYPE(M6504, m6504_device, "m6504", "MOS Technology 6504")
m6504_device::m6504_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, M6504, tag, owner, clock)
{
program_config.m_addr_width = 13;
+ program_config.m_logaddr_width = 13;
sprogram_config.m_addr_width = 13;
-}
-
-void m6504_device::device_start()
-{
- if(cache_disabled)
- mintf = std::make_unique<mi_6504_nd>();
- else
- mintf = std::make_unique<mi_6504_normal>();
-
- init();
-}
-
-uint8_t m6504_device::mi_6504_normal::read(uint16_t adr)
-{
- return program->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6504_device::mi_6504_normal::read_sync(uint16_t adr)
-{
- return scache->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6504_device::mi_6504_normal::read_arg(uint16_t adr)
-{
- return cache->read_byte(adr & 0x1fff);
-}
-
-void m6504_device::mi_6504_normal::write(uint16_t adr, uint8_t val)
-{
- program->write_byte(adr & 0x1fff, val);
-}
-
-uint8_t m6504_device::mi_6504_nd::read_sync(uint16_t adr)
-{
- return sprogram->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6504_device::mi_6504_nd::read_arg(uint16_t adr)
-{
- return program->read_byte(adr & 0x1fff);
+ sprogram_config.m_logaddr_width = 13;
}
diff --git a/src/devices/cpu/m6502/m6504.h b/src/devices/cpu/m6502/m6504.h
index 6238d510b18..b33f3713062 100644
--- a/src/devices/cpu/m6502/m6504.h
+++ b/src/devices/cpu/m6502/m6504.h
@@ -16,32 +16,11 @@
class m6504_device : public m6502_device {
public:
m6504_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- class mi_6504_normal : public memory_interface {
- public:
- virtual ~mi_6504_normal() {}
- virtual uint8_t read(uint16_t adr) override;
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- virtual void write(uint16_t adr, uint8_t val) override;
- };
-
- class mi_6504_nd : public mi_6504_normal {
- public:
- virtual ~mi_6504_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
- virtual void device_start() override;
};
enum {
- M6504_IRQ_LINE = m6502_device::IRQ_LINE,
- M6504_NMI_LINE = m6502_device::NMI_LINE,
- M6504_SET_OVERFLOW = m6502_device::V_LINE
+ M6504_IRQ_LINE = m6502_device::IRQ_LINE
};
DECLARE_DEVICE_TYPE(M6504, m6504_device);
diff --git a/src/devices/cpu/m6502/m6507.cpp b/src/devices/cpu/m6502/m6507.cpp
index ea97cf260e9..ae1c984f1d1 100644
--- a/src/devices/cpu/m6502/m6507.cpp
+++ b/src/devices/cpu/m6502/m6507.cpp
@@ -2,60 +2,24 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6507.c
+ m6507.cpp
MOS Technology 6502, NMOS variant with reduced address bus
+ 28-pin package, address bus is 13 bits, no NMI, no SO, no SYNC.
+
***************************************************************************/
#include "emu.h"
#include "m6507.h"
-DEFINE_DEVICE_TYPE(M6507, m6507_device, "m6507", "MOS Technology M6507")
+DEFINE_DEVICE_TYPE(M6507, m6507_device, "m6507", "MOS Technology 6507")
m6507_device::m6507_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, M6507, tag, owner, clock)
{
program_config.m_addr_width = 13;
+ program_config.m_logaddr_width = 13;
sprogram_config.m_addr_width = 13;
-}
-
-void m6507_device::device_start()
-{
- if(cache_disabled)
- mintf = std::make_unique<mi_6507_nd>();
- else
- mintf = std::make_unique<mi_6507_normal>();
-
- init();
-}
-
-uint8_t m6507_device::mi_6507_normal::read(uint16_t adr)
-{
- return program->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6507_device::mi_6507_normal::read_sync(uint16_t adr)
-{
- return scache->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6507_device::mi_6507_normal::read_arg(uint16_t adr)
-{
- return cache->read_byte(adr & 0x1fff);
-}
-
-void m6507_device::mi_6507_normal::write(uint16_t adr, uint8_t val)
-{
- program->write_byte(adr & 0x1fff, val);
-}
-
-uint8_t m6507_device::mi_6507_nd::read_sync(uint16_t adr)
-{
- return sprogram->read_byte(adr & 0x1fff);
-}
-
-uint8_t m6507_device::mi_6507_nd::read_arg(uint16_t adr)
-{
- return program->read_byte(adr & 0x1fff);
+ sprogram_config.m_logaddr_width = 13;
}
diff --git a/src/devices/cpu/m6502/m6507.h b/src/devices/cpu/m6502/m6507.h
index 350891637bc..30b51dce74c 100644
--- a/src/devices/cpu/m6502/m6507.h
+++ b/src/devices/cpu/m6502/m6507.h
@@ -16,32 +16,11 @@
class m6507_device : public m6502_device {
public:
m6507_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- class mi_6507_normal : public memory_interface {
- public:
- virtual ~mi_6507_normal() {}
- virtual uint8_t read(uint16_t adr) override;
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- virtual void write(uint16_t adr, uint8_t val) override;
- };
-
- class mi_6507_nd : public mi_6507_normal {
- public:
- virtual ~mi_6507_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
- virtual void device_start() override;
};
enum {
- M6507_IRQ_LINE = m6502_device::IRQ_LINE,
- M6507_NMI_LINE = m6502_device::NMI_LINE,
- M6507_SET_OVERFLOW = m6502_device::V_LINE
+ M6507_IRQ_LINE = m6502_device::IRQ_LINE
};
DECLARE_DEVICE_TYPE(M6507, m6507_device)
diff --git a/src/devices/cpu/m6502/m6509.cpp b/src/devices/cpu/m6502/m6509.cpp
index 95c2d62b79a..dd4eca50c83 100644
--- a/src/devices/cpu/m6502/m6509.cpp
+++ b/src/devices/cpu/m6502/m6509.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6509.c
+ m6509.cpp
6502 with banking and extended address bus
@@ -12,7 +12,7 @@
#include "m6509.h"
#include "m6509d.h"
-DEFINE_DEVICE_TYPE(M6509, m6509_device, "m6509", "MOS Technology M6509")
+DEFINE_DEVICE_TYPE(M6509, m6509_device, "m6509", "MOS Technology 6509")
m6509_device::m6509_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, M6509, tag, owner, clock), bank_i(0), bank_y(0)
@@ -25,10 +25,7 @@ m6509_device::m6509_device(const machine_config &mconfig, const char *tag, devic
void m6509_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_6509_nd>(this);
- else
- mintf = std::make_unique<mi_6509_normal>(this);
+ mintf = std::make_unique<mi_6509>(this);
init();
@@ -55,14 +52,14 @@ std::unique_ptr<util::disasm_interface> m6509_device::create_disassembler()
return std::make_unique<m6509_disassembler>();
}
-m6509_device::mi_6509_normal::mi_6509_normal(m6509_device *_base)
+m6509_device::mi_6509::mi_6509(m6509_device *_base)
{
base = _base;
}
-uint8_t m6509_device::mi_6509_normal::read(uint16_t adr)
+uint8_t m6509_device::mi_6509::read(uint16_t adr)
{
- uint8_t res = program->read_byte(base->adr_in_bank_i(adr));
+ uint8_t res = program.read_byte(base->adr_in_bank_i(adr));
if(adr == 0x0000)
res = base->bank_i_r();
else if(adr == 0x0001)
@@ -70,9 +67,9 @@ uint8_t m6509_device::mi_6509_normal::read(uint16_t adr)
return res;
}
-uint8_t m6509_device::mi_6509_normal::read_sync(uint16_t adr)
+uint8_t m6509_device::mi_6509::read_sync(uint16_t adr)
{
- uint8_t res = scache->read_byte(base->adr_in_bank_i(adr));
+ uint8_t res = csprogram.read_byte(base->adr_in_bank_i(adr));
if(adr == 0x0000)
res = base->bank_i_r();
else if(adr == 0x0001)
@@ -80,9 +77,9 @@ uint8_t m6509_device::mi_6509_normal::read_sync(uint16_t adr)
return res;
}
-uint8_t m6509_device::mi_6509_normal::read_arg(uint16_t adr)
+uint8_t m6509_device::mi_6509::read_arg(uint16_t adr)
{
- uint8_t res = cache->read_byte(base->adr_in_bank_i(adr));
+ uint8_t res = cprogram.read_byte(base->adr_in_bank_i(adr));
if(adr == 0x0000)
res = base->bank_i_r();
else if(adr == 0x0001)
@@ -90,9 +87,9 @@ uint8_t m6509_device::mi_6509_normal::read_arg(uint16_t adr)
return res;
}
-uint8_t m6509_device::mi_6509_normal::read_9(uint16_t adr)
+uint8_t m6509_device::mi_6509::read_9(uint16_t adr)
{
- uint8_t res = program->read_byte(base->adr_in_bank_y(adr));
+ uint8_t res = program.read_byte(base->adr_in_bank_y(adr));
if(adr == 0x0000)
res = base->bank_i_r();
else if(adr == 0x0001)
@@ -100,46 +97,22 @@ uint8_t m6509_device::mi_6509_normal::read_9(uint16_t adr)
return res;
}
-void m6509_device::mi_6509_normal::write(uint16_t adr, uint8_t val)
+void m6509_device::mi_6509::write(uint16_t adr, uint8_t val)
{
- program->write_byte(base->adr_in_bank_i(adr), val);
+ program.write_byte(base->adr_in_bank_i(adr), val);
if(adr == 0x0000)
base->bank_i_w(val);
else if(adr == 0x0001)
base->bank_y_w(val);
}
-void m6509_device::mi_6509_normal::write_9(uint16_t adr, uint8_t val)
+void m6509_device::mi_6509::write_9(uint16_t adr, uint8_t val)
{
- program->write_byte(base->adr_in_bank_y(adr), val);
+ program.write_byte(base->adr_in_bank_y(adr), val);
if(adr == 0x0000)
base->bank_i_w(val);
else if(adr == 0x0001)
base->bank_y_w(val);
}
-m6509_device::mi_6509_nd::mi_6509_nd(m6509_device *_base) : mi_6509_normal(_base)
-{
-}
-
-uint8_t m6509_device::mi_6509_nd::read_sync(uint16_t adr)
-{
- uint8_t res = sprogram->read_byte(base->adr_in_bank_i(adr));
- if(adr == 0x0000)
- res = base->bank_i_r();
- else if(adr == 0x0001)
- res = base->bank_y_r();
- return res;
-}
-
-uint8_t m6509_device::mi_6509_nd::read_arg(uint16_t adr)
-{
- uint8_t res = program->read_byte(base->adr_in_bank_i(adr));
- if(adr == 0x0000)
- res = base->bank_i_r();
- else if(adr == 0x0001)
- res = base->bank_y_r();
- return res;
-}
-
#include "cpu/m6502/m6509.hxx"
diff --git a/src/devices/cpu/m6502/m6509.h b/src/devices/cpu/m6502/m6509.h
index 0d9a536e71f..383bfcc178a 100644
--- a/src/devices/cpu/m6502/m6509.h
+++ b/src/devices/cpu/m6502/m6509.h
@@ -22,12 +22,12 @@ public:
virtual void do_exec_partial() override;
protected:
- class mi_6509_normal : public memory_interface {
+ class mi_6509 : public memory_interface {
public:
m6509_device *base;
- mi_6509_normal(m6509_device *base);
- virtual ~mi_6509_normal() {}
+ mi_6509(m6509_device *base);
+ virtual ~mi_6509() {}
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_9(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
@@ -36,16 +36,8 @@ protected:
virtual void write_9(uint16_t adr, uint8_t val) override;
};
- class mi_6509_nd : public mi_6509_normal {
- public:
- mi_6509_nd(m6509_device *base);
- virtual ~mi_6509_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual offs_t pc_to_external(u16 pc) override;
uint8_t bank_i, bank_y;
diff --git a/src/devices/cpu/m6502/m6510.cpp b/src/devices/cpu/m6502/m6510.cpp
index b045d4423f5..c54965a2f04 100644
--- a/src/devices/cpu/m6502/m6510.cpp
+++ b/src/devices/cpu/m6502/m6510.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6510.c
+ m6510.cpp
6502 with 6 i/o pins, also known as 8500
@@ -15,8 +15,8 @@
#include "m6510.h"
#include "m6510d.h"
-DEFINE_DEVICE_TYPE(M6510, m6510_device, "m6510", "MOS Technology M6510")
-DEFINE_DEVICE_TYPE(M6508, m6508_device, "m6508", "MOS Technology M6508")
+DEFINE_DEVICE_TYPE(M6510, m6510_device, "m6510", "MOS Technology 6510")
+DEFINE_DEVICE_TYPE(M6508, m6508_device, "m6508", "MOS Technology 6508")
m6510_device::m6510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6510_device(mconfig, M6510, tag, owner, clock)
@@ -25,8 +25,9 @@ m6510_device::m6510_device(const machine_config &mconfig, const char *tag, devic
m6510_device::m6510_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, type, tag, owner, clock),
- read_port(*this),
- write_port(*this), dir(0), port(0), drive(0)
+ read_port(*this, 0),
+ write_port(*this),
+ dir(0), port(0), drive(0)
{
pullup = 0x00;
floating = 0x00;
@@ -45,9 +46,6 @@ std::unique_ptr<util::disasm_interface> m6510_device::create_disassembler()
void m6510_device::init_port()
{
- read_port.resolve_safe(0);
- write_port.resolve_safe();
-
save_item(NAME(pullup));
save_item(NAME(floating));
save_item(NAME(dir));
@@ -57,10 +55,7 @@ void m6510_device::init_port()
void m6510_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_6510_nd>(this);
- else
- mintf = std::make_unique<mi_6510_normal>(this);
+ mintf = std::make_unique<mi_6510>(this);
init();
init_port();
@@ -69,9 +64,9 @@ void m6510_device::device_start()
void m6510_device::device_reset()
{
m6502_device::device_reset();
- dir = 0x00;
- port = 0x00;
- drive = 0x00;
+ dir = 0xff;
+ port = 0xff;
+ drive = 0xff;
update_port();
}
@@ -109,14 +104,14 @@ void m6510_device::port_w(uint8_t data)
}
-m6510_device::mi_6510_normal::mi_6510_normal(m6510_device *_base)
+m6510_device::mi_6510::mi_6510(m6510_device *_base)
{
base = _base;
}
-uint8_t m6510_device::mi_6510_normal::read(uint16_t adr)
+uint8_t m6510_device::mi_6510::read(uint16_t adr)
{
- uint8_t res = program->read_byte(adr);
+ uint8_t res = program.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -124,9 +119,9 @@ uint8_t m6510_device::mi_6510_normal::read(uint16_t adr)
return res;
}
-uint8_t m6510_device::mi_6510_normal::read_sync(uint16_t adr)
+uint8_t m6510_device::mi_6510::read_sync(uint16_t adr)
{
- uint8_t res = scache->read_byte(adr);
+ uint8_t res = csprogram.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -134,9 +129,9 @@ uint8_t m6510_device::mi_6510_normal::read_sync(uint16_t adr)
return res;
}
-uint8_t m6510_device::mi_6510_normal::read_arg(uint16_t adr)
+uint8_t m6510_device::mi_6510::read_arg(uint16_t adr)
{
- uint8_t res = cache->read_byte(adr);
+ uint8_t res = cprogram.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -144,39 +139,15 @@ uint8_t m6510_device::mi_6510_normal::read_arg(uint16_t adr)
return res;
}
-void m6510_device::mi_6510_normal::write(uint16_t adr, uint8_t val)
+void m6510_device::mi_6510::write(uint16_t adr, uint8_t val)
{
- program->write_byte(adr, val);
+ program.write_byte(adr, val);
if(adr == 0x0000)
base->dir_w(val);
else if(adr == 0x0001)
base->port_w(val);
}
-m6510_device::mi_6510_nd::mi_6510_nd(m6510_device *_base) : mi_6510_normal(_base)
-{
-}
-
-uint8_t m6510_device::mi_6510_nd::read_sync(uint16_t adr)
-{
- uint8_t res = sprogram->read_byte(adr);
- if(adr == 0x0000)
- res = base->dir_r();
- else if(adr == 0x0001)
- res = base->port_r();
- return res;
-}
-
-uint8_t m6510_device::mi_6510_nd::read_arg(uint16_t adr)
-{
- uint8_t res = program->read_byte(adr);
- if(adr == 0x0000)
- res = base->dir_r();
- else if(adr == 0x0001)
- res = base->port_r();
- return res;
-}
-
m6508_device::m6508_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6510_device(mconfig, M6508, tag, owner, clock)
@@ -185,10 +156,7 @@ m6508_device::m6508_device(const machine_config &mconfig, const char *tag, devic
void m6508_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_6508_nd>(this);
- else
- mintf = std::make_unique<mi_6508_normal>(this);
+ mintf = std::make_unique<mi_6508>(this);
init();
init_port();
@@ -198,14 +166,14 @@ void m6508_device::device_start()
}
-m6508_device::mi_6508_normal::mi_6508_normal(m6508_device *_base)
+m6508_device::mi_6508::mi_6508(m6508_device *_base)
{
base = _base;
}
-uint8_t m6508_device::mi_6508_normal::read(uint16_t adr)
+uint8_t m6508_device::mi_6508::read(uint16_t adr)
{
- uint8_t res = program->read_byte(adr);
+ uint8_t res = program.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -215,9 +183,9 @@ uint8_t m6508_device::mi_6508_normal::read(uint16_t adr)
return res;
}
-uint8_t m6508_device::mi_6508_normal::read_sync(uint16_t adr)
+uint8_t m6508_device::mi_6508::read_sync(uint16_t adr)
{
- uint8_t res = scache->read_byte(adr);
+ uint8_t res = csprogram.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -227,9 +195,9 @@ uint8_t m6508_device::mi_6508_normal::read_sync(uint16_t adr)
return res;
}
-uint8_t m6508_device::mi_6508_normal::read_arg(uint16_t adr)
+uint8_t m6508_device::mi_6508::read_arg(uint16_t adr)
{
- uint8_t res = cache->read_byte(adr);
+ uint8_t res = cprogram.read_byte(adr);
if(adr == 0x0000)
res = base->dir_r();
else if(adr == 0x0001)
@@ -239,9 +207,9 @@ uint8_t m6508_device::mi_6508_normal::read_arg(uint16_t adr)
return res;
}
-void m6508_device::mi_6508_normal::write(uint16_t adr, uint8_t val)
+void m6508_device::mi_6508::write(uint16_t adr, uint8_t val)
{
- program->write_byte(adr, val);
+ program.write_byte(adr, val);
if(adr == 0x0000)
base->dir_w(val);
else if(adr == 0x0001)
@@ -250,33 +218,5 @@ void m6508_device::mi_6508_normal::write(uint16_t adr, uint8_t val)
base->ram_page[adr & 0x00ff] = val;
}
-m6508_device::mi_6508_nd::mi_6508_nd(m6508_device *_base) : mi_6508_normal(_base)
-{
-}
-
-uint8_t m6508_device::mi_6508_nd::read_sync(uint16_t adr)
-{
- uint8_t res = sprogram->read_byte(adr);
- if(adr == 0x0000)
- res = base->dir_r();
- else if(adr == 0x0001)
- res = base->port_r();
- else if(adr < 0x0200)
- res = base->ram_page[adr & 0x00ff];
- return res;
-}
-
-uint8_t m6508_device::mi_6508_nd::read_arg(uint16_t adr)
-{
- uint8_t res = program->read_byte(adr);
- if(adr == 0x0000)
- res = base->dir_r();
- else if(adr == 0x0001)
- res = base->port_r();
- else if(adr < 0x0200)
- res = base->ram_page[adr & 0x00ff];
- return res;
-}
-
#include "cpu/m6502/m6510.hxx"
diff --git a/src/devices/cpu/m6502/m6510.h b/src/devices/cpu/m6502/m6510.h
index 773acee9294..b7d4e585b86 100644
--- a/src/devices/cpu/m6502/m6510.h
+++ b/src/devices/cpu/m6502/m6510.h
@@ -7,6 +7,7 @@
6502 with 6 i/o pins, also known as 8500
***************************************************************************/
+
#ifndef MAME_CPU_M6502_M6510_H
#define MAME_CPU_M6502_M6510_H
@@ -31,33 +32,25 @@ public:
protected:
m6510_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- class mi_6510_normal : public memory_interface {
+ class mi_6510 : public memory_interface {
public:
m6510_device *base;
- mi_6510_normal(m6510_device *base);
- virtual ~mi_6510_normal() {}
+ mi_6510(m6510_device *base);
+ virtual ~mi_6510() {}
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
virtual uint8_t read_arg(uint16_t adr) override;
virtual void write(uint16_t adr, uint8_t val) override;
};
- class mi_6510_nd : public mi_6510_normal {
- public:
- mi_6510_nd(m6510_device *base);
- virtual ~mi_6510_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
devcb_read8 read_port;
devcb_write8 write_port;
uint8_t pullup, floating, dir, port, drive;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t dir_r();
void dir_w(uint8_t data);
@@ -86,28 +79,20 @@ public:
m6508_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- class mi_6508_normal : public memory_interface {
+ class mi_6508 : public memory_interface {
public:
m6508_device *base;
- mi_6508_normal(m6508_device *base);
- virtual ~mi_6508_normal() {}
+ mi_6508(m6508_device *base);
+ virtual ~mi_6508() {}
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
virtual uint8_t read_arg(uint16_t adr) override;
virtual void write(uint16_t adr, uint8_t val) override;
};
- class mi_6508_nd : public mi_6508_normal {
- public:
- mi_6508_nd(m6508_device *base);
- virtual ~mi_6508_nd() {}
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
std::unique_ptr<uint8_t[]> ram_page;
};
diff --git a/src/devices/cpu/m6502/m6510t.cpp b/src/devices/cpu/m6502/m6510t.cpp
index 83d3cc5527e..3290040c0ab 100644
--- a/src/devices/cpu/m6502/m6510t.cpp
+++ b/src/devices/cpu/m6502/m6510t.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m6510t.c
+ m6510t.cpp
6510 with the full 8 i/o pins at the expense of the NMI and RDY lines.
@@ -11,7 +11,7 @@
#include "emu.h"
#include "m6510t.h"
-DEFINE_DEVICE_TYPE(M6510T, m6510t_device, "m6510t", "MOS Technology M6510T")
+DEFINE_DEVICE_TYPE(M6510T, m6510t_device, "m6510t", "MOS Technology 6510T")
m6510t_device::m6510t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6510_device(mconfig, M6510T, tag, owner, clock)
diff --git a/src/devices/cpu/m6502/m65c02.cpp b/src/devices/cpu/m6502/m65c02.cpp
deleted file mode 100644
index 80df7c79921..00000000000
--- a/src/devices/cpu/m6502/m65c02.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
- m65c02.c
-
- MOS Technology 6502, CMOS variant with some additional instructions
- (but not the bitwise ones)
-
-***************************************************************************/
-
-#include "emu.h"
-#include "m65c02.h"
-#include "m65c02d.h"
-
-DEFINE_DEVICE_TYPE(M65C02, m65c02_device, "m65c02", "MOS Technology M65C02")
-
-m65c02_device::m65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- m6502_device(mconfig, M65C02, tag, owner, clock)
-{
-}
-
-m65c02_device::m65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m6502_device(mconfig, type, tag, owner, clock)
-{
-}
-
-std::unique_ptr<util::disasm_interface> m65c02_device::create_disassembler()
-{
- return std::make_unique<m65c02_disassembler>();
-}
-
-#include "cpu/m6502/m65c02.hxx"
diff --git a/src/devices/cpu/m6502/m65ce02.cpp b/src/devices/cpu/m6502/m65ce02.cpp
index e336e936545..22e6bd5f3c5 100644
--- a/src/devices/cpu/m6502/m65ce02.cpp
+++ b/src/devices/cpu/m6502/m65ce02.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m65ce02.c
+ m65ce02.cpp
6502 with Z register and some more stuff
@@ -12,7 +12,7 @@
#include "m65ce02.h"
#include "m65ce02d.h"
-DEFINE_DEVICE_TYPE(M65CE02, m65ce02_device, "m65ce02", "MOS Technology M65CE02")
+DEFINE_DEVICE_TYPE(M65CE02, m65ce02_device, "m65ce02", "CSG 65CE02")
m65ce02_device::m65ce02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m65ce02_device(mconfig, M65CE02, tag, owner, clock)
@@ -20,7 +20,7 @@ m65ce02_device::m65ce02_device(const machine_config &mconfig, const char *tag, d
}
m65ce02_device::m65ce02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m65c02_device(mconfig, type, tag, owner, clock), TMP3(0), Z(0), B(0)
+ w65c02_device(mconfig, type, tag, owner, clock), TMP3(0), Z(0), B(0)
{
}
@@ -31,7 +31,7 @@ std::unique_ptr<util::disasm_interface> m65ce02_device::create_disassembler()
void m65ce02_device::init()
{
- m65c02_device::init();
+ w65c02_device::init();
state_add(M65CE02_Z, "Z", Z);
state_add(M65CE02_B, "B", B).callimport().formatstr("%2s");
save_item(NAME(B));
@@ -44,17 +44,14 @@ void m65ce02_device::init()
void m65ce02_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_default_nd>();
- else
- mintf = std::make_unique<mi_default_normal>();
+ mintf = std::make_unique<mi_default>();
init();
}
void m65ce02_device::device_reset()
{
- m65c02_device::device_reset();
+ w65c02_device::device_reset();
Z = 0x00;
B = 0x0000;
}
diff --git a/src/devices/cpu/m6502/m65ce02.h b/src/devices/cpu/m6502/m65ce02.h
index 6e27c66e010..cf0a48e9a5b 100644
--- a/src/devices/cpu/m6502/m65ce02.h
+++ b/src/devices/cpu/m6502/m65ce02.h
@@ -12,9 +12,9 @@
#pragma once
-#include "m65c02.h"
+#include "w65c02.h"
-class m65ce02_device : public m65c02_device {
+class m65ce02_device : public w65c02_device {
public:
m65ce02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -30,8 +30,8 @@ protected:
uint16_t B; /* Zero page base address (always xx00) */
virtual void init() override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void state_import(const device_state_entry &entry) override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
diff --git a/src/devices/cpu/m6502/m65sc02.cpp b/src/devices/cpu/m6502/m65sc02.cpp
deleted file mode 100644
index b92ad8d0678..00000000000
--- a/src/devices/cpu/m6502/m65sc02.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
- m65sc02.c
-
- Rockwell-class 65c02 with internal static registers, making clock stoppable?
-
-***************************************************************************/
-
-#include "emu.h"
-#include "m65sc02.h"
-
-DEFINE_DEVICE_TYPE(M65SC02, m65sc02_device, "m65sc02", "Rockwell M65SC02")
-
-m65sc02_device::m65sc02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- r65c02_device(mconfig, M65SC02, tag, owner, clock)
-{
-}
diff --git a/src/devices/cpu/m6502/m65sc02.h b/src/devices/cpu/m6502/m65sc02.h
deleted file mode 100644
index 686411c0b22..00000000000
--- a/src/devices/cpu/m6502/m65sc02.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
- m65sc02.h
-
- Rockwell-class 65c02 with internal static registers, making clock stoppable?
-
-***************************************************************************/
-
-#ifndef MAME_CPU_M6502_M65SC02_H
-#define MAME_CPU_M6502_M65SC02_H
-
-#include "r65c02.h"
-
-class m65sc02_device : public r65c02_device {
-public:
- m65sc02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-enum {
- M65SC02_IRQ_LINE = m6502_device::IRQ_LINE,
- M65SC02_NMI_LINE = m6502_device::NMI_LINE,
- M65SC02_SET_OVERFLOW = m6502_device::V_LINE
-};
-
-DECLARE_DEVICE_TYPE(M65SC02, m65sc02_device)
-
-#endif // MAME_CPU_M6502_M65SC02_H
diff --git a/src/devices/cpu/m6502/m740.cpp b/src/devices/cpu/m6502/m740.cpp
index 684bff6773b..4e42db0cb67 100644
--- a/src/devices/cpu/m6502/m740.cpp
+++ b/src/devices/cpu/m6502/m740.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m740.c
+ m740.cpp
Mitsubishi M740 series (M507xx/M509xx)
@@ -11,13 +11,6 @@
#include "emu.h"
#include "m740.h"
-DEFINE_DEVICE_TYPE(M740, m740_device, "m740", "Mitsubishi M740")
-
-m740_device::m740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- m740_device(mconfig, M740, tag, owner, clock)
-{
-}
-
m740_device::m740_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, type, tag, owner, clock), m_irq_multiplex(0), m_irq_vector(0)
{
@@ -43,18 +36,11 @@ void m740_device::device_start()
void m740_device::device_reset()
{
- inst_state_base = 0;
- inst_state = STATE_RESET;
- inst_substate = 0;
- nmi_state = false;
+ m6502_device::device_reset();
+
irq_state = false;
m_irq_multiplex = 0;
m_irq_vector = 0xfffc;
- apu_irq_state = false;
- irq_taken = false;
- v_state = false;
- sync = false;
- inhibit_interrupts = false;
SP = 0x00ff;
}
@@ -96,37 +82,37 @@ void m740_device::do_sbc_dt(uint8_t val)
{
uint8_t c = P & F_C ? 0 : 1;
P &= ~(F_N|F_V|F_Z|F_C);
- uint16_t diff = TMP2 - val - c;
- uint8_t al = (TMP2 & 15) - (val & 15) - c;
+ uint16_t diff = TMP - val - c;
+ uint8_t al = (TMP & 15) - (val & 15) - c;
if(int8_t(al) < 0)
al -= 6;
- uint8_t ah = (TMP2 >> 4) - (val >> 4) - (int8_t(al) < 0);
+ uint8_t ah = (TMP >> 4) - (val >> 4) - (int8_t(al) < 0);
if(!uint8_t(diff))
P |= F_Z;
else if(diff & 0x80)
P |= F_N;
- if((TMP2^val) & (TMP2^diff) & 0x80)
+ if((TMP^val) & (TMP^diff) & 0x80)
P |= F_V;
if(!(diff & 0xff00))
P |= F_C;
if(int8_t(ah) < 0)
ah -= 6;
- TMP2 = (ah << 4) | (al & 15);
+ TMP = (ah << 4) | (al & 15);
}
void m740_device::do_sbc_ndt(uint8_t val)
{
- uint16_t diff = TMP2 - val - (P & F_C ? 0 : 1);
+ uint16_t diff = TMP - val - (P & F_C ? 0 : 1);
P &= ~(F_N|F_V|F_Z|F_C);
if(!uint8_t(diff))
P |= F_Z;
else if(int8_t(diff) < 0)
P |= F_N;
- if((TMP2^val) & (TMP2^diff) & 0x80)
+ if((TMP^val) & (TMP^diff) & 0x80)
P |= F_V;
if(!(diff & 0xff00))
P |= F_C;
- TMP2 = diff;
+ TMP = diff;
}
void m740_device::do_sbct(uint8_t val)
@@ -141,37 +127,37 @@ void m740_device::do_adc_dt(uint8_t val)
{
uint8_t c = P & F_C ? 1 : 0;
P &= ~(F_N|F_V|F_Z|F_C);
- uint8_t al = (TMP2 & 15) + (val & 15) + c;
+ uint8_t al = (TMP & 15) + (val & 15) + c;
if(al > 9)
al += 6;
- uint8_t ah = (TMP2 >> 4) + (val >> 4) + (al > 15);
- if(!uint8_t(TMP2 + val + c))
+ uint8_t ah = (TMP >> 4) + (val >> 4) + (al > 15);
+ if(!uint8_t(TMP + val + c))
P |= F_Z;
else if(ah & 8)
P |= F_N;
- if(~(TMP2^val) & (TMP2^(ah << 4)) & 0x80)
+ if(~(TMP^val) & (TMP^(ah << 4)) & 0x80)
P |= F_V;
if(ah > 9)
ah += 6;
if(ah > 15)
P |= F_C;
- TMP2 = (ah << 4) | (al & 15);
+ TMP = (ah << 4) | (al & 15);
}
void m740_device::do_adc_ndt(uint8_t val)
{
uint16_t sum;
- sum = TMP2 + val + (P & F_C ? 1 : 0);
+ sum = TMP + val + (P & F_C ? 1 : 0);
P &= ~(F_N|F_V|F_Z|F_C);
if(!uint8_t(sum))
P |= F_Z;
else if(int8_t(sum) < 0)
P |= F_N;
- if(~(TMP2^val) & (TMP2^sum) & 0x80)
+ if(~(TMP^val) & (TMP^sum) & 0x80)
P |= F_V;
if(sum & 0xff00)
P |= F_C;
- TMP2 = sum;
+ TMP = sum;
}
void m740_device::do_adct(uint8_t val)
diff --git a/src/devices/cpu/m6502/m740.h b/src/devices/cpu/m6502/m740.h
index 352f0a4be5c..6c64c0af79c 100644
--- a/src/devices/cpu/m6502/m740.h
+++ b/src/devices/cpu/m6502/m740.h
@@ -33,23 +33,24 @@ public:
M740_INT12_LINE, // (ffe4)
M740_INT13_LINE, // (ffe2)
M740_INT14_LINE, // (ffe0)
- M740_MAX_INT_LINE = M740_INT14_LINE,
- M740_SET_OVERFLOW = m6502_device::V_LINE
+ M740_MAX_INT_LINE = M740_INT14_LINE
};
- m740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+ virtual void read_dummy(uint16_t adr) { (void)mintf->read(adr); }
+ virtual uint8_t read_data(uint16_t adr) { return mintf->read(adr); }
+ virtual void write_data(uint16_t adr, uint8_t val) { mintf->write(adr, val); }
+
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void do_exec_full() override;
virtual void do_exec_partial() override;
virtual void execute_set_input(int inputnum, int state) override;
-protected:
m740_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
#define O(o) void o ## _full(); void o ## _partial()
@@ -67,29 +68,64 @@ protected:
void do_adct(uint8_t val);
// m740 opcodes
- O(brk740_imp);
+ O(brk_m_imp);
O(clt_imp);
O(set_imp);
O(ldm_imz);
+ O(dec_acc);
+ O(inc_acc);
O(jsr_spg);
- O(reset740);
+ O(reset_m);
O(seb_biz); O(seb_bac);
O(clb_biz); O(clb_bac);
O(bbc_bzr); O(bbc_bar);
O(bbs_bzr); O(bbs_bar);
+ O(com_zpg);
O(rrf_zpg);
+ O(tst_zpg);
O(bra_rel);
O(jmp_zpi);
+ O(jsr_zpi);
+ O(stp_imp);
+ O(wit_imp);
+
+ O(adc_m_abx); O(adc_m_aby); O(adc_m_idx); O(adc_m_idy); O(adc_m_zpx);
+ O(and_m_abx); O(and_m_aby); O(and_m_idx); O(and_m_idy); O(and_m_zpx);
+ O(asl_m_aba); O(asl_m_abx); O(asl_m_zpg); O(asl_m_zpx);
+ O(bcc_m_rel);
+ O(bcs_m_rel);
+ O(beq_m_rel);
+ O(bmi_m_rel);
+ O(bne_m_rel);
+ O(bpl_m_rel);
+ O(bvc_m_rel);
+ O(bvs_m_rel);
+ O(cmp_m_abx); O(cmp_m_aby); O(cmp_m_idx); O(cmp_m_idy); O(cmp_m_zpx);
+ O(dec_m_aba); O(dec_m_abx); O(dec_m_zpg); O(dec_m_zpx);
+ O(eor_m_abx); O(eor_m_aby); O(eor_m_idx); O(eor_m_idy); O(eor_m_zpx);
+ O(inc_m_aba); O(inc_m_abx); O(inc_m_zpg); O(inc_m_zpx);
+ O(jmp_m_ind);
+ O(jsr_m_adr);
+ O(lda_m_abx); O(lda_m_aby); O(lda_m_idx); O(lda_m_idy); O(lda_m_zpx);
+ O(ldx_m_aby); O(ldx_m_zpg); O(ldx_m_zpy);
+ O(ldy_m_abx); O(ldy_m_zpg); O(ldy_m_zpx);
+ O(lsr_m_aba); O(lsr_m_abx); O(lsr_m_zpg); O(lsr_m_zpx);
+ O(ora_m_abx); O(ora_m_aby); O(ora_m_idx); O(ora_m_idy); O(ora_m_zpx);
+ O(pla_m_imp);
+ O(plp_m_imp);
+ O(rol_m_aba); O(rol_m_abx); O(rol_m_zpg); O(rol_m_zpx);
+ O(ror_m_aba); O(ror_m_abx); O(ror_m_zpg); O(ror_m_zpx);
+ O(rti_m_imp);
+ O(rts_m_imp);
+ O(sbc_m_abx); O(sbc_m_aby); O(sbc_m_idx); O(sbc_m_idy); O(sbc_m_zpx);
+ O(sta_m_aba); O(sta_m_abx); O(sta_m_aby); O(sta_m_idx); O(sta_m_idy); O(sta_m_zpg); O(sta_m_zpx);
+ O(stx_m_aba); O(stx_m_zpg); O(stx_m_zpy);
+ O(sty_m_aba); O(sty_m_zpg); O(sty_m_zpx);
O(adct_aba); O(adct_abx); O(adct_aby); O(adct_idx); O(adct_idy); O(adct_imm); O(adct_zpg); O(adct_zpx);
O(andt_aba); O(andt_abx); O(andt_aby); O(andt_imm); O(andt_idx); O(andt_idy); O(andt_zpg); O(andt_zpx);
O(cmpt_aba); O(cmpt_abx); O(cmpt_aby); O(cmpt_idx); O(cmpt_idy); O(cmpt_imm); O(cmpt_zpg); O(cmpt_zpx);
- O(com_zpg);
- O(dec_acc);
- O(dect_acc);
O(eort_aba); O(eort_abx); O(eort_aby); O(eort_idx); O(eort_idy); O(eort_imm); O(eort_zpg); O(eort_zpx);
- O(inc_acc);
- O(inct_acc);
O(ldt_aba); O(ldt_abx); O(ldt_aby); O(ldt_idx); O(ldt_idy); O(ldt_imm); O(ldt_zpg); O(ldt_zpx);
O(ort_aba); O(ort_abx); O(ort_aby); O(ort_imm); O(ort_idx); O(ort_idy); O(ort_zpg); O(ort_zpx);
O(sbct_aba); O(sbct_abx); O(sbct_aby); O(sbct_idx); O(sbct_idy); O(sbct_imm); O(sbct_zpg); O(sbct_zpx);
@@ -102,6 +138,4 @@ protected:
void set_irq_line(int line, int state);
};
-DECLARE_DEVICE_TYPE(M740, m740_device)
-
#endif // MAME_CPU_M6502_M740_H
diff --git a/src/devices/cpu/m6502/m7501.cpp b/src/devices/cpu/m6502/m7501.cpp
index 912a7a023dd..30921d1664f 100644
--- a/src/devices/cpu/m6502/m7501.cpp
+++ b/src/devices/cpu/m6502/m7501.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m7501.c
+ m7501.cpp
6510 derivative, essentially identical. Also known as the 8501.
@@ -11,7 +11,7 @@
#include "emu.h"
#include "m7501.h"
-DEFINE_DEVICE_TYPE(M7501, m7501_device, "m7501", "M7501")
+DEFINE_DEVICE_TYPE(M7501, m7501_device, "m7501", "MOS Technology 7501")
m7501_device::m7501_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6510_device(mconfig, M7501, tag, owner, clock)
diff --git a/src/devices/cpu/m6502/m8502.cpp b/src/devices/cpu/m6502/m8502.cpp
index 75a4a2f7b25..3227d2b0c88 100644
--- a/src/devices/cpu/m6502/m8502.cpp
+++ b/src/devices/cpu/m6502/m8502.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m8502.c
+ m8502.cpp
6510 derivative, capable of running at 2MHz.
@@ -11,7 +11,7 @@
#include "emu.h"
#include "m8502.h"
-DEFINE_DEVICE_TYPE(M8502, m8502_device, "m8502", "M8502")
+DEFINE_DEVICE_TYPE(M8502, m8502_device, "m8502", "MOS Technology 8502")
m8502_device::m8502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6510_device(mconfig, M8502, tag, owner, clock)
diff --git a/src/devices/cpu/m6502/n2a03.cpp b/src/devices/cpu/m6502/n2a03.cpp
deleted file mode 100644
index 6bfbc2edc98..00000000000
--- a/src/devices/cpu/m6502/n2a03.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
- n2a03.cpp
-
- 6502, NES variant
-
-***************************************************************************/
-
-#include "emu.h"
-#include "n2a03.h"
-#include "n2a03d.h"
-
-DEFINE_DEVICE_TYPE(N2A03, n2a03_device, "n2a03", "Ricoh N2A03")
-
-READ8_MEMBER(n2a03_device::psg1_4014_r)
-{
- return m_apu->read(0x14);
-}
-
-READ8_MEMBER(n2a03_device::psg1_4015_r)
-{
- return m_apu->read(0x15);
-}
-
-WRITE8_MEMBER(n2a03_device::psg1_4015_w)
-{
- m_apu->write(0x15, data);
-}
-
-WRITE8_MEMBER(n2a03_device::psg1_4017_w)
-{
- m_apu->write(0x17, data);
-}
-
-
-// on various drivers output port 0x4014 is used for external hardware (not used by APU?)
-// input/output port 0x4016 ^ (not used by APU?)
-// input port 0x4017 ^ ( APU_IRQCTRL )
-// is there a fall through where every write is seen by other hw, or do these addresses really not touch the APU?? APU_IRQCTRL can definitely be written by can it be read back?
-
-void n2a03_device::n2a03_map(address_map &map)
-{
- map(0x4000, 0x4013).rw("nesapu", FUNC(nesapu_device::read), FUNC(nesapu_device::write));
- map(0x4014, 0x4014).r(FUNC(n2a03_device::psg1_4014_r)); // AM_WRITE(sprite_dma_0_w)
- map(0x4015, 0x4015).rw(FUNC(n2a03_device::psg1_4015_r), FUNC(n2a03_device::psg1_4015_w)); /* PSG status / first control register */
- //map(0x4016, 0x4016).rw(FUNC(n2a03_device::vsnes_in0_r), FUNC(n2a03_device::vsnes_in0_w));
- map(0x4017, 0x4017) /*.r(FUNC(n2a03_device::vsnes_in1_r))*/ .w(FUNC(n2a03_device::psg1_4017_w));
-}
-
-
-
-n2a03_device::n2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : m6502_device(mconfig, N2A03, tag, owner, clock)
- , device_mixer_interface(mconfig, *this, 1)
- , m_apu(*this, "nesapu")
-{
- program_config.m_internal_map = address_map_constructor(FUNC(n2a03_device::n2a03_map), this);
-}
-
-std::unique_ptr<util::disasm_interface> n2a03_device::create_disassembler()
-{
- return std::make_unique<n2a03_disassembler>();
-}
-
-WRITE_LINE_MEMBER(n2a03_device::apu_irq)
-{
- // games relying on the APU_IRQ don't seem to work anyway? (nes software list : timelord, mig29sf, firehawk)
- set_input_line(N2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
-}
-
-READ8_MEMBER(n2a03_device::apu_read_mem)
-{
- return mintf->program->read_byte(offset);
-}
-
-void n2a03_device::device_add_mconfig(machine_config &config)
-{
- NES_APU(config, m_apu, DERIVED_CLOCK(1,1));
- m_apu->irq().set(FUNC(n2a03_device::apu_irq));
- m_apu->mem_read().set(FUNC(n2a03_device::apu_read_mem));
- m_apu->add_route(ALL_OUTPUTS, *this, 1.0, AUTO_ALLOC_INPUT, 0);
-}
-
-
-#include "cpu/m6502/n2a03.hxx"
diff --git a/src/devices/cpu/m6502/n2a03.h b/src/devices/cpu/m6502/n2a03.h
deleted file mode 100644
index d11d4d86a1c..00000000000
--- a/src/devices/cpu/m6502/n2a03.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
- n2a03.h
-
- 6502, NES variant
-
-***************************************************************************/
-#ifndef MAME_CPU_M6502_N2A03_H
-#define MAME_CPU_M6502_N2A03_H
-
-#pragma once
-
-#include "m6502.h"
-#include "sound/nes_apu.h"
-
-class n2a03_device : public m6502_device, public device_mixer_interface {
-public:
- n2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- virtual void do_exec_full() override;
- virtual void do_exec_partial() override;
-
- READ8_MEMBER(psg1_4014_r);
- READ8_MEMBER(psg1_4015_r);
- WRITE8_MEMBER(psg1_4015_w);
- WRITE8_MEMBER(psg1_4017_w);
-
- void n2a03_map(address_map &map);
-protected:
-#define O(o) void o ## _full(); void o ## _partial()
-
- // n2a03 opcodes - same as 6502 with D disabled
- O(adc_nd_aba); O(adc_nd_abx); O(adc_nd_aby); O(adc_nd_idx); O(adc_nd_idy); O(adc_nd_imm); O(adc_nd_zpg); O(adc_nd_zpx);
- O(arr_nd_imm);
- O(isb_nd_aba); O(isb_nd_abx); O(isb_nd_aby); O(isb_nd_idx); O(isb_nd_idy); O(isb_nd_zpg); O(isb_nd_zpx);
- O(rra_nd_aba); O(rra_nd_abx); O(rra_nd_aby); O(rra_nd_idx); O(rra_nd_idy); O(rra_nd_zpg); O(rra_nd_zpx);
- O(sbc_nd_aba); O(sbc_nd_abx); O(sbc_nd_aby); O(sbc_nd_idx); O(sbc_nd_idy); O(sbc_nd_imm); O(sbc_nd_zpg); O(sbc_nd_zpx);
-
-#undef O
-
- required_device<nesapu_device> m_apu;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(apu_irq);
- DECLARE_READ8_MEMBER(apu_read_mem);
-
-};
-
-/* These are the official XTAL values and clock rates used by Nintendo for
- manufacturing throughout the production of the 2A03. PALC_APU_CLOCK is
- the clock rate devised by UMC(?) for PAL Famicom clone hardware. */
-
-#define N2A03_NTSC_XTAL XTAL(21'477'272)
-#define N2A03_PAL_XTAL XTAL(26'601'712)
-#define NTSC_APU_CLOCK (N2A03_NTSC_XTAL/12) /* 1.7897726666... MHz */
-#define PAL_APU_CLOCK (N2A03_PAL_XTAL/16) /* 1.662607 MHz */
-#define PALC_APU_CLOCK (N2A03_PAL_XTAL/15) /* 1.77344746666... MHz */
-
-enum {
- N2A03_IRQ_LINE = m6502_device::IRQ_LINE,
- N2A03_APU_IRQ_LINE = m6502_device::APU_IRQ_LINE,
- N2A03_NMI_LINE = m6502_device::NMI_LINE,
- N2A03_SET_OVERFLOW = m6502_device::V_LINE
-};
-
-DECLARE_DEVICE_TYPE(N2A03, n2a03_device)
-
-#endif // MAME_CPU_M6502_N2A03_H
diff --git a/src/devices/cpu/m6502/odeco16.lst b/src/devices/cpu/m6502/odeco16.lst
index 694eb2f3613..1f25b6b3be6 100644
--- a/src/devices/cpu/m6502/odeco16.lst
+++ b/src/devices/cpu/m6502/odeco16.lst
@@ -2,11 +2,12 @@
# copyright-holders:Olivier Galibert
# deco 16 opcodes
brk_16_imp
- // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
+ // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending)
if(irq_taken) {
- read_pc_noinc();
+ read_pc();
} else {
read_pc();
+ PC++;
}
write(SP, PC >> 8);
dec_SP();
@@ -14,16 +15,16 @@ brk_16_imp
dec_SP();
write(SP, irq_taken ? P & ~F_B : P);
dec_SP();
- if(nmi_state) {
+ if(nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
PC = read_arg(0xfff7);
PC = set_h(PC, read_arg(0xfff6));
- nmi_state = false;
- standard_irq_callback(NMI_LINE);
+ nmi_pending = false;
} else {
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
PC = read_arg(0xfff3);
PC = set_h(PC, read_arg(0xfff2));
- if(irq_taken)
- standard_irq_callback(IRQ_LINE);
}
irq_taken = false;
P |= F_I; // Do *not* move after the prefetch
@@ -36,41 +37,48 @@ ill_non
u0B_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OP0B %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
u13_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OP13 %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
u23_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OP23 %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
u3F_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OPBB %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
u4B_zpg
TMP2 = read_pc();
+ PC++;
A = io->read_byte(1);
prefetch();
u87_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OP87 %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
u8F_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OP8F (BANK) %02x (%04x)\n", tag(), NPC, TMP2);
io->write_byte(0, TMP2);
@@ -78,18 +86,21 @@ u8F_zpg
uA3_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OPA3 %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
uBB_zpg
TMP2 = read_pc();
+ PC++;
if(DECO16_VERBOSE)
logerror("%s: OPBB %02x (%04x)\n", tag(), NPC, TMP2);
prefetch();
vbl_zpg
TMP2 = read_pc();
+ PC++;
A = io->read_byte(0);
//if(DECO16_VERBOSE)
// logerror("%s: VBL %02x (%04x)\n", tag(), NPC, TMP2);
@@ -97,7 +108,8 @@ vbl_zpg
# exceptions
reset_16
- P |= F_I; PC = read_arg(0xfff1);
+ P |= F_I;
+ PC = read_arg(0xfff1);
PC = set_h(PC, read_arg(0xfff0));
prefetch();
inst_state = -1;
diff --git a/src/devices/cpu/m6502/om6502.lst b/src/devices/cpu/m6502/om6502.lst
index d34e63c1d81..1dca3d918a8 100644
--- a/src/devices/cpu/m6502/om6502.lst
+++ b/src/devices/cpu/m6502/om6502.lst
@@ -6,141 +6,175 @@
adc_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
adc_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
adc_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
adc_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_adc(read(TMP));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
adc_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_adc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_adc(TMP2);
prefetch();
adc_imm
TMP = read_pc();
+ PC++;
do_adc(TMP);
prefetch();
adc_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
adc_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_adc(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_adc(TMP2);
prefetch();
and_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- A &= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_imm
- A &= read_pc();
+ TMP = read_pc();
+ PC++;
+ A &= TMP;
set_nz(A);
prefetch();
and_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- A &= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A &= TMP2;
set_nz(A);
prefetch();
and_zpg
TMP = read_pc();
- A &= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- A &= read(uint8_t(TMP+X));
+ TMP2 = read(uint8_t(TMP+X));
+ A &= TMP2;
set_nz(A);
prefetch();
asl_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_asl(TMP2);
@@ -149,7 +183,9 @@ asl_aba
asl_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -159,12 +195,13 @@ asl_abx
prefetch();
asl_acc
- read_pc_noinc();
+ read_pc();
A = do_asl(A);
prefetch();
asl_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_asl(TMP2);
@@ -173,6 +210,7 @@ asl_zpg
asl_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -183,8 +221,9 @@ asl_zpx
bcc_rel
TMP = read_pc();
+ PC++;
if(!(P & F_C)) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -194,8 +233,9 @@ bcc_rel
bcs_rel
TMP = read_pc();
+ PC++;
if(P & F_C) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -205,8 +245,9 @@ bcs_rel
beq_rel
TMP = read_pc();
+ PC++;
if(P & F_Z) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -216,19 +257,25 @@ beq_rel
bit_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- do_bit(read(TMP));
+ PC++;
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bit_zpg
TMP = read_pc();
- do_bit(read(TMP));
+ PC++;
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bmi_rel
TMP = read_pc();
+ PC++;
if(P & F_N) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -238,8 +285,9 @@ bmi_rel
bne_rel
TMP = read_pc();
+ PC++;
if(!(P & F_Z)) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -249,8 +297,9 @@ bne_rel
bpl_rel
TMP = read_pc();
+ PC++;
if(!(P & F_N)) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -259,11 +308,12 @@ bpl_rel
prefetch();
brk_imp
- // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
+ // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending)
if(irq_taken) {
- read_pc_noinc();
+ read_pc();
} else {
read_pc();
+ PC++;
}
write(SP, PC >> 8);
dec_SP();
@@ -271,16 +321,16 @@ brk_imp
dec_SP();
write(SP, irq_taken ? P & ~F_B : P);
dec_SP();
- if(nmi_state) {
+ if(nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb));
- nmi_state = false;
- standard_irq_callback(NMI_LINE);
+ nmi_pending = false;
} else {
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
PC = read_arg(0xfffe);
PC = set_h(PC, read_arg(0xffff));
- if(irq_taken)
- standard_irq_callback(IRQ_LINE);
}
irq_taken = false;
P |= F_I; // Do *not* move after the prefetch
@@ -289,8 +339,9 @@ brk_imp
bvc_rel
TMP = read_pc();
+ PC++;
if(!(P & F_V)) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -300,8 +351,9 @@ bvc_rel
bvs_rel
TMP = read_pc();
+ PC++;
if(P & F_V) {
- read_pc_noinc();
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -310,130 +362,153 @@ bvs_rel
prefetch();
clc_imp
- read_pc_noinc();
+ read_pc();
P &= ~F_C;
prefetch();
cld_imp
- read_pc_noinc();
+ read_pc();
P &= ~F_D;
prefetch();
cli_imp
- read_pc_noinc();
+ read_pc();
prefetch();
P &= ~F_I; // Do *not* move it before the prefetch
clv_imp
- read_pc_noinc();
+ read_pc();
P &= ~F_V;
prefetch();
cmp_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_cmp(A, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_cmp(A, TMP);
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_cmp(A, TMP);
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_cmp(A, read(TMP));
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_cmp(A, read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_cmp(A, TMP2);
prefetch();
cmp_imm
TMP = read_pc();
+ PC++;
do_cmp(A, TMP);
prefetch();
cmp_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_cmp(A, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_cmp(A, TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_cmp(A, TMP2);
prefetch();
cpx_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_cmp(X, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(X, TMP2);
prefetch();
cpx_imm
TMP = read_pc();
+ PC++;
do_cmp(X, TMP);
prefetch();
cpx_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_cmp(X, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(X, TMP2);
prefetch();
cpy_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_cmp(Y, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(Y, TMP2);
prefetch();
cpy_imm
TMP = read_pc();
+ PC++;
do_cmp(Y, TMP);
prefetch();
cpy_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_cmp(Y, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(Y, TMP2);
prefetch();
dec_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2--;
@@ -443,7 +518,9 @@ dec_aba
dec_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -455,6 +532,7 @@ dec_abx
dec_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2--;
@@ -464,6 +542,7 @@ dec_zpg
dec_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -474,88 +553,109 @@ dec_zpx
prefetch();
dex_imp
- read_pc_noinc();
+ read_pc();
X--;
set_nz(X);
prefetch();
dey_imp
- read_pc_noinc();
+ read_pc();
Y--;
set_nz(Y);
prefetch();
eor_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- A ^= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- A ^= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_imm
- A ^= read_pc();
+ TMP = read_pc();
+ PC++;
+ A ^= TMP;
set_nz(A);
prefetch();
eor_zpg
TMP = read_pc();
- A ^= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- A ^= read(uint8_t(TMP+X));
+ TMP2 = read(uint8_t(TMP+X));
+ A ^= TMP2;
set_nz(A);
prefetch();
inc_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -565,7 +665,9 @@ inc_aba
inc_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -577,6 +679,7 @@ inc_abx
inc_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -586,6 +689,7 @@ inc_zpg
inc_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -596,32 +700,36 @@ inc_zpx
prefetch();
inx_imp
- read_pc_noinc();
+ read_pc();
X++;
set_nz(X);
prefetch();
iny_imp
- read_pc_noinc();
+ read_pc();
Y++;
set_nz(Y);
prefetch();
jmp_adr
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
PC = TMP;
prefetch();
jmp_ind
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
PC = set_h(PC, read(set_l(TMP, TMP+1)));
prefetch();
jsr_adr
TMP = read_pc();
+ PC++;
read(SP);
write(SP, PC>>8);
dec_SP();
@@ -633,14 +741,18 @@ jsr_adr
lda_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
A = read(TMP);
set_nz(A);
prefetch();
lda_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
@@ -650,7 +762,9 @@ lda_abx
lda_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
@@ -660,6 +774,7 @@ lda_aby
lda_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -670,6 +785,7 @@ lda_idx
lda_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
@@ -681,17 +797,20 @@ lda_idy
lda_imm
A = read_pc();
+ PC++;
set_nz(A);
prefetch();
lda_zpg
TMP = read_pc();
+ PC++;
A = read(TMP);
set_nz(A);
prefetch();
lda_zpx
TMP = read_pc();
+ PC++;
read(TMP);
A = read(uint8_t(TMP+X));
set_nz(A);
@@ -699,14 +818,18 @@ lda_zpx
ldx_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
X = read(TMP);
set_nz(X);
prefetch();
ldx_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
@@ -716,17 +839,20 @@ ldx_aby
ldx_imm
X = read_pc();
+ PC++;
set_nz(X);
prefetch();
ldx_zpg
TMP = read_pc();
+ PC++;
X = read(TMP);
set_nz(X);
prefetch();
ldx_zpy
TMP = read_pc();
+ PC++;
read(TMP);
X = read(uint8_t(TMP+Y));
set_nz(X);
@@ -734,14 +860,18 @@ ldx_zpy
ldy_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
Y = read(TMP);
set_nz(Y);
prefetch();
ldy_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
@@ -752,17 +882,20 @@ ldy_abx
ldy_imm
Y = read_pc();
+ PC++;
set_nz(Y);
prefetch();
ldy_zpg
TMP = read_pc();
+ PC++;
Y = read(TMP);
set_nz(Y);
prefetch();
ldy_zpx
TMP = read_pc();
+ PC++;
read(TMP);
Y = read(uint8_t(TMP+X));
set_nz(Y);
@@ -770,7 +903,9 @@ ldy_zpx
lsr_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_lsr(TMP2);
@@ -779,7 +914,9 @@ lsr_aba
lsr_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -789,12 +926,13 @@ lsr_abx
prefetch();
lsr_acc
- read_pc_noinc();
+ read_pc();
A = do_lsr(A);
prefetch();
lsr_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_lsr(TMP2);
@@ -803,6 +941,7 @@ lsr_zpg
lsr_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -812,91 +951,110 @@ lsr_zpx
prefetch();
nop_imp
- read_pc_noinc();
+ read_pc();
prefetch();
ora_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- A |= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_imm
- A |= read_pc();
+ TMP = read_pc();
+ PC++;
+ A |= TMP;
set_nz(A);
prefetch();
ora_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- A |= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_zpg
TMP = read_pc();
- A |= read(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- A |= read(uint8_t(TMP+X));
+ TMP2 = read(uint8_t(TMP+X));
+ A |= TMP2;
set_nz(A);
prefetch();
pha_imp
- read_pc_noinc();
+ read_pc();
write(SP, A);
dec_SP();
prefetch();
php_imp
- read_pc_noinc();
+ read_pc();
write(SP, P);
dec_SP();
prefetch();
pla_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
A = read(SP);
@@ -904,7 +1062,7 @@ pla_imp
prefetch();
plp_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
TMP = read(SP) | (F_B|F_E);
@@ -913,7 +1071,9 @@ plp_imp
rol_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_rol(TMP2);
@@ -922,7 +1082,9 @@ rol_aba
rol_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -932,12 +1094,13 @@ rol_abx
prefetch();
rol_acc
- read_pc_noinc();
+ read_pc();
A = do_rol(A);
prefetch();
rol_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_rol(TMP2);
@@ -946,6 +1109,7 @@ rol_zpg
rol_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -956,7 +1120,9 @@ rol_zpx
ror_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -965,7 +1131,9 @@ ror_aba
ror_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -975,12 +1143,13 @@ ror_abx
prefetch();
ror_acc
- read_pc_noinc();
+ read_pc();
A = do_ror(A);
prefetch();
ror_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -989,6 +1158,7 @@ ror_zpg
ror_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -998,7 +1168,7 @@ ror_zpx
prefetch();
rti_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
P = read(SP) | (F_B|F_E);
@@ -1009,118 +1179,139 @@ rti_imp
prefetch();
rts_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
PC = read(SP);
inc_SP();
PC = set_h(PC, read(SP));
read_pc();
+ PC++;
prefetch();
sbc_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sbc_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sbc_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sbc_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_sbc(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sbc_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_sbc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_sbc(TMP2);
prefetch();
sbc_imm
TMP = read_pc();
+ PC++;
do_sbc(TMP);
prefetch();
sbc_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sbc_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_sbc(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_sbc(TMP2);
prefetch();
sec_imp
- read_pc_noinc();
+ read_pc();
P |= F_C;
prefetch();
sed_imp
- read_pc_noinc();
+ read_pc();
P |= F_D;
prefetch();
sei_imp
- read_pc_noinc();
+ read_pc();
prefetch();
P |= F_I; // Do *not* move it before the prefetch
sta_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP, A);
prefetch();
sta_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
write(TMP+X, A);
prefetch();
sta_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
write(TMP+Y, A);
prefetch();
sta_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1130,6 +1321,7 @@ sta_idx
sta_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1138,92 +1330,106 @@ sta_idy
sta_zpg
TMP = read_pc();
+ PC++;
write(TMP, A);
prefetch();
sta_zpx
TMP = read_pc();
+ PC++;
read(TMP);
write(uint8_t(TMP+X), A);
prefetch();
stx_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP, X);
prefetch();
stx_zpg
TMP = read_pc();
+ PC++;
write(TMP, X);
prefetch();
stx_zpy
TMP = read_pc();
+ PC++;
read(TMP);
write(uint8_t(TMP+Y), X);
prefetch();
sty_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP, Y);
prefetch();
sty_zpg
TMP = read_pc();
+ PC++;
write(TMP, Y);
prefetch();
sty_zpx
TMP = read_pc();
+ PC++;
read(TMP);
write(uint8_t(TMP+X), Y);
prefetch();
tax_imp
- read_pc_noinc();
+ read_pc();
X = A;
set_nz(X);
prefetch();
tay_imp
- read_pc_noinc();
+ read_pc();
Y = A;
set_nz(Y);
prefetch();
tsx_imp
- read_pc_noinc();
+ read_pc();
X = SP;
set_nz(X);
prefetch();
txa_imp
- read_pc_noinc();
+ read_pc();
A = X;
set_nz(A);
prefetch();
txs_imp
- read_pc_noinc();
+ read_pc();
SP = set_l(SP, X);
prefetch();
tya_imp
- read_pc_noinc();
+ read_pc();
A = Y;
set_nz(A);
prefetch();
# exceptions
reset
- read_pc_noinc();
- read_pc_noinc();
- read(SP); dec_SP();
- read(SP); dec_SP();
- read(SP); dec_SP();
- P |= F_I; PC = read_arg(0xfffc);
+ read_pc();
+ read_pc();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ P |= F_I;
+ PC = read_arg(0xfffc);
PC = set_h(PC, read_arg(0xfffd));
prefetch();
inst_state = -1;
@@ -1232,7 +1438,9 @@ reset
# undocumented reliable instructions
dcp_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2--;
@@ -1242,7 +1450,9 @@ dcp_aba
dcp_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1254,7 +1464,9 @@ dcp_abx
dcp_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1266,6 +1478,7 @@ dcp_aby
dcp_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1279,6 +1492,7 @@ dcp_idx
dcp_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1292,6 +1506,7 @@ dcp_idy
dcp_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2--;
@@ -1301,6 +1516,7 @@ dcp_zpg
dcp_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1312,7 +1528,9 @@ dcp_zpx
isb_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -1322,7 +1540,9 @@ isb_aba
isb_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1334,7 +1554,9 @@ isb_abx
isb_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1346,6 +1568,7 @@ isb_aby
isb_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1359,6 +1582,7 @@ isb_idx
isb_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1372,6 +1596,7 @@ isb_idy
isb_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -1381,6 +1606,7 @@ isb_zpg
isb_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1392,14 +1618,18 @@ isb_zpx
lax_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
A = X = read(TMP);
set_nz(A);
prefetch();
lax_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
@@ -1409,6 +1639,7 @@ lax_aby
lax_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1419,6 +1650,7 @@ lax_idx
lax_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
@@ -1430,12 +1662,14 @@ lax_idy
lax_zpg
TMP = read_pc();
+ PC++;
A = X = read(TMP);
set_nz(A);
prefetch();
lax_zpy
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+Y);
A = X = read(TMP);
@@ -1444,7 +1678,9 @@ lax_zpy
rla_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_rol(TMP2);
@@ -1455,7 +1691,9 @@ rla_aba
rla_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1468,7 +1706,9 @@ rla_abx
rla_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1481,6 +1721,7 @@ rla_aby
rla_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1495,6 +1736,7 @@ rla_idx
rla_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1509,6 +1751,7 @@ rla_idy
rla_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_rol(TMP2);
@@ -1519,6 +1762,7 @@ rla_zpg
rla_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1531,7 +1775,9 @@ rla_zpx
rra_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -1541,7 +1787,9 @@ rra_aba
rra_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1553,7 +1801,9 @@ rra_abx
rra_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1565,6 +1815,7 @@ rra_aby
rra_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1578,6 +1829,7 @@ rra_idx
rra_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1591,6 +1843,7 @@ rra_idy
rra_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -1600,6 +1853,7 @@ rra_zpg
rra_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1611,13 +1865,16 @@ rra_zpx
sax_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = A & X;
write(TMP, TMP2);
prefetch();
sax_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1628,12 +1885,14 @@ sax_idx
sax_zpg
TMP = read_pc();
+ PC++;
TMP2 = A & X;
write(TMP, TMP2);
prefetch();
sax_zpy
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+Y);
TMP2 = A & X;
@@ -1642,6 +1901,7 @@ sax_zpy
sbx_imm
TMP2 = read_pc();
+ PC++;
X &= A;
if(X < TMP2)
P &= ~F_C;
@@ -1653,7 +1913,9 @@ sbx_imm
sha_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP2 = A & X & ((TMP >> 8)+1);
if(page_changing(TMP, Y))
@@ -1665,6 +1927,7 @@ sha_aby
sha_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1678,7 +1941,9 @@ sha_idy
shs_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
SP = set_l(SP, A & X);
TMP2 = A & X & ((TMP >> 8)+1);
@@ -1691,7 +1956,9 @@ shs_aby
shx_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP2 = X & ((TMP >> 8)+1);
if(page_changing(TMP, Y))
@@ -1703,7 +1970,9 @@ shx_aby
shy_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP2 = Y & ((TMP >> 8)+1);
if(page_changing(TMP, X))
@@ -1715,7 +1984,9 @@ shy_abx
slo_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_asl(TMP2);
@@ -1726,7 +1997,9 @@ slo_aba
slo_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1739,7 +2012,9 @@ slo_abx
slo_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1752,6 +2027,7 @@ slo_aby
slo_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1766,6 +2042,7 @@ slo_idx
slo_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1780,6 +2057,7 @@ slo_idy
slo_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_asl(TMP2);
@@ -1790,6 +2068,7 @@ slo_zpg
slo_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1802,7 +2081,9 @@ slo_zpx
sre_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_lsr(TMP2);
@@ -1813,7 +2094,9 @@ sre_aba
sre_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -1826,7 +2109,9 @@ sre_abx
sre_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -1839,6 +2124,7 @@ sre_aby
sre_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -1853,6 +2139,7 @@ sre_idx
sre_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -1867,6 +2154,7 @@ sre_idy
sre_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_lsr(TMP2);
@@ -1877,6 +2165,7 @@ sre_zpg
sre_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -1889,7 +2178,9 @@ sre_zpx
# undocumented unreliable instructions
anc_imm
- A &= read_pc();
+ TMP = read_pc();
+ PC++;
+ A &= TMP;
set_nz(A);
if(A & 0x80)
P |= F_C;
@@ -1898,24 +2189,30 @@ anc_imm
prefetch();
ane_imm
- TMP2 = read_pc();
- A &= TMP2 & X;
+ TMP = read_pc();
+ PC++;
+ A &= TMP & X;
set_nz(A);
prefetch();
asr_imm
- A &= read_pc();
- A = do_lsr(A);
+ TMP = read_pc();
+ PC++;
+ A = do_lsr(A & TMP);
prefetch();
arr_imm
- A &= read_pc();
+ TMP = read_pc();
+ PC++;
+ A &= TMP;
do_arr();
prefetch();
las_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
@@ -1927,19 +2224,24 @@ las_aby
lxa_imm
A = X = read_pc();
+ PC++;
set_nz(A);
prefetch();
# nop variants
nop_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(TMP);
prefetch();
nop_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
@@ -1948,15 +2250,18 @@ nop_abx
nop_imm
read_pc();
+ PC++;
prefetch();
nop_zpg
TMP = read_pc();
+ PC++;
read(TMP);
prefetch();
nop_zpx
TMP = read_pc();
+ PC++;
read(TMP);
read(uint8_t(TMP+X));
prefetch();
@@ -1964,6 +2269,7 @@ nop_zpx
# system killers
kil_non
read_pc();
+ PC++;
read(0xffff);
read(0xfffe);
read(0xfffe);
diff --git a/src/devices/cpu/m6502/om6509.lst b/src/devices/cpu/m6502/om6509.lst
index 8c9a6f9baa1..b2f116716e8 100644
--- a/src/devices/cpu/m6502/om6509.lst
+++ b/src/devices/cpu/m6502/om6509.lst
@@ -4,6 +4,7 @@
lda_9_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
@@ -15,6 +16,7 @@ lda_9_idy
sta_9_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read_9(set_l(TMP, TMP+Y));
diff --git a/src/devices/cpu/m6502/om6510.lst b/src/devices/cpu/m6502/om6510.lst
index 1ad0dfc0182..1554e83de95 100644
--- a/src/devices/cpu/m6502/om6510.lst
+++ b/src/devices/cpu/m6502/om6510.lst
@@ -3,6 +3,7 @@
# 6510 undocumented instructions in a C64 context
anc_10_imm
TMP2 = read_pc();
+ PC++;
A &= TMP2;
set_nz(A);
if(A & 0x80)
@@ -13,25 +14,30 @@ anc_10_imm
ane_10_imm
TMP2 = read_pc();
+ PC++;
A = (A | 0xee) & TMP2 & X;
set_nz(A);
prefetch();
asr_10_imm
TMP2 = read_pc();
+ PC++;
A = do_lsr(A & TMP2);
set_nz(A);
prefetch();
arr_10_imm
TMP2 = read_pc();
+ PC++;
A &= TMP2;
do_arr();
prefetch();
las_10_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
@@ -43,6 +49,7 @@ las_10_aby
lxa_10_imm
TMP2 = read_pc();
+ PC++;
A = X = (A | 0xee) & TMP2;
set_nz(A);
prefetch();
diff --git a/src/devices/cpu/m6502/om65ce02.lst b/src/devices/cpu/m6502/om65ce02.lst
index 85648fd610d..800ce84488d 100644
--- a/src/devices/cpu/m6502/om65ce02.lst
+++ b/src/devices/cpu/m6502/om65ce02.lst
@@ -4,66 +4,79 @@
adc_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_adc(read(TMP));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_adc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_adc(read(TMP+Z));
+ TMP2 = read(TMP+Z);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_imm
TMP = read_pc();
+ PC++;
do_adc(TMP);
if(P & F_D)
set_nz(A);
@@ -71,79 +84,99 @@ adc_ce_imm
adc_ce_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
adc_ce_zpx
TMP = read_pc();
- TMP = read(B|uint8_t(TMP+X));
- do_adc(TMP);
+ PC++;
+ TMP2 = read(B|uint8_t(TMP+X));
+ do_adc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
and_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A &= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A &= TMP2;
set_nz(A);
prefetch();
and_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A &= read(TMP+Z);
+ TMP2 = read(TMP+Z);
+ A &= TMP2;
set_nz(A);
prefetch();
and_ce_zpg
TMP = read_pc();
- A &= read(B|TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
and_ce_zpx
TMP = read_pc();
- A &= read(B|uint8_t(TMP+X));
+ PC++;
+ TMP2 = read(B|uint8_t(TMP+X));
+ A &= TMP2;
set_nz(A);
prefetch();
asl_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2 = do_asl(TMP2);
write(TMP, TMP2);
@@ -151,7 +184,9 @@ asl_ce_aba
asl_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
TMP2 = read(TMP);
TMP2 = do_asl(TMP2);
@@ -164,6 +199,7 @@ asl_ce_acc
asl_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 = do_asl(TMP2);
write(TMP, TMP2);
@@ -171,6 +207,7 @@ asl_ce_zpg
asl_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2 = do_asl(TMP2);
@@ -183,6 +220,7 @@ asr_acc
asr_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 = do_asr(TMP2);
write(TMP, TMP2);
@@ -190,6 +228,7 @@ asr_zpg
asr_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2 = do_asr(TMP2);
@@ -198,7 +237,9 @@ asr_zpx
asw_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP3 = read(TMP);
TMP3 = set_h(TMP3, read(TMP+1));
P &= ~(F_C|F_N|F_Z);
@@ -215,15 +256,20 @@ asw_aba
aug_iw3
read_pc();
+ PC++;
read_pc();
+ PC++;
read_pc();
+ PC++;
prefetch();
bbr_ce_zpb
// Access pattern uncertain
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
TMP = read_pc();
+ PC++;
if(!(TMP2 & (1 << ((inst_state >> 4) & 7))))
PC += int8_t(TMP);
prefetch();
@@ -231,140 +277,170 @@ bbr_ce_zpb
bbs_ce_zpb
// Access pattern uncertain
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
TMP = read_pc();
+ PC++;
if(TMP2 & (1 << ((inst_state >> 4) & 7)))
PC += int8_t(TMP);
prefetch();
bcc_ce_rel
TMP = read_pc();
+ PC++;
if(!(P & F_C))
PC += int8_t(TMP);
prefetch();
bcc_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(!(P & F_C))
PC += TMP-1;
prefetch();
bcs_ce_rel
TMP = read_pc();
+ PC++;
if(P & F_C)
PC += int8_t(TMP);
prefetch();
bcs_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(P & F_C)
PC += TMP-1;
prefetch();
beq_ce_rel
TMP = read_pc();
+ PC++;
if(P & F_Z)
PC += int8_t(TMP);
prefetch();
beq_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(P & F_Z)
PC += TMP-1;
prefetch();
bit_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- do_bit(read(TMP));
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bit_ce_imm
TMP = read_pc();
+ PC++;
do_bit(TMP);
prefetch();
bit_ce_zpg
TMP = B|read_pc();
- do_bit(read(TMP));
+ PC++;
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bit_ce_zpx
TMP = read_pc();
- TMP = read(B|uint8_t(TMP+X));
- do_bit(TMP);
+ PC++;
+ TMP2 = read(B|uint8_t(TMP+X));
+ do_bit(TMP2);
prefetch();
bmi_ce_rel
TMP = read_pc();
+ PC++;
if(P & F_N)
PC += int8_t(TMP);
prefetch();
bmi_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(P & F_N)
PC += TMP-1;
prefetch();
bne_ce_rel
TMP = read_pc();
+ PC++;
if(!(P & F_Z))
PC += int8_t(TMP);
prefetch();
bne_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(!(P & F_Z))
PC += TMP-1;
prefetch();
bpl_ce_rel
TMP = read_pc();
+ PC++;
if(!(P & F_N))
PC += int8_t(TMP);
prefetch();
bpl_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(!(P & F_N))
PC += TMP-1;
prefetch();
bra_ce_rel
TMP = read_pc();
+ PC++;
PC += int8_t(TMP);
prefetch();
bra_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- PC += TMP - 1;
+ PC += TMP;
prefetch();
brk_ce_imp
if(irq_taken) {
- read_pc_noinc();
+ read_pc();
} else {
read_pc();
+ PC++;
}
write(SP, PC >> 8);
dec_SP_ce();
write(SP, PC);
dec_SP_ce();
- write(SP, irq_taken || nmi_state ? P & ~F_B : P);
+ write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
dec_SP_ce();
- if(nmi_state) {
+ if(nmi_pending) {
PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb));
- nmi_state = false;
+ nmi_pending = false;
} else {
PC = read_arg(0xfffe);
PC = set_h(PC, read_arg(0xffff));
@@ -376,36 +452,44 @@ brk_ce_imp
bsr_rw2
TMP = read_pc();
+ PC++;
write(SP, PC>>8);
dec_SP_ce();
write(SP, PC);
dec_SP_ce();
TMP = set_h(TMP, read_pc());
+ PC++;
PC += TMP-1;
prefetch();
bvc_ce_rel
TMP = read_pc();
+ PC++;
if(!(P & F_V))
PC += int8_t(TMP);
prefetch();
bvc_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(!(P & F_V))
PC += TMP-1;
prefetch();
bvs_ce_rel
TMP = read_pc();
+ PC++;
if(P & F_V)
PC += int8_t(TMP);
prefetch();
bvs_rw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(P & F_V)
PC += TMP-1;
prefetch();
@@ -419,7 +503,7 @@ cld_ce_imp
prefetch();
cle_imp
- read_pc_noinc();
+ read_pc();
P &= ~F_E;
logerror("CLE\n");
prefetch();
@@ -434,91 +518,111 @@ clv_ce_imp
cmp_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- TMP = read(TMP);
- do_cmp(A, TMP);
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- TMP = read(TMP);
- do_cmp(A, TMP);
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_cmp(A, read(TMP));
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_cmp(A, read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_cmp(A, TMP2);
prefetch();
cmp_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_cmp(A, read(TMP+Z));
+ TMP2 = read(TMP+Z);
+ do_cmp(A, TMP2);
prefetch();
cmp_ce_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_cmp(A, TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_cmp(A, TMP2);
prefetch();
cmp_ce_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(B|uint8_t(TMP+X));
- do_cmp(A, TMP);
+ TMP2 = read(B|uint8_t(TMP+X));
+ do_cmp(A, TMP2);
prefetch();
cpx_ce_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_cmp(X, TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_cmp(X, TMP2);
prefetch();
cpy_ce_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_cmp(Y, TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_cmp(Y, TMP2);
prefetch();
cpz_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_cmp(Z, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_cmp(Z, TMP2);
prefetch();
cpz_imm
TMP = read_pc();
+ PC++;
do_cmp(Z, TMP);
prefetch();
cpz_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_cmp(Z, TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_cmp(Z, TMP2);
prefetch();
dec_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2--;
set_nz(TMP2);
@@ -527,7 +631,9 @@ dec_ce_aba
dec_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
TMP2 = read(TMP);
TMP2--;
@@ -542,6 +648,7 @@ dec_ce_acc
dec_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2--;
set_nz(TMP2);
@@ -550,6 +657,7 @@ dec_ce_zpg
dec_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2--;
@@ -559,16 +667,17 @@ dec_ce_zpx
dew_zpg
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
P &= ~(F_N|F_Z);
- TMP++;
+ TMP--;
if(!TMP)
P |= F_Z;
else if(TMP & 0x8000)
P |= F_N;
- TMP2++;
+ TMP2--;
write(B|TMP2, TMP);
TMP2++;
write(B|TMP2, TMP >> 8);
@@ -591,63 +700,81 @@ dez_imp
eor_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A ^= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A ^= read(TMP+Z);
+ TMP2 = read(TMP+Z);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_ce_zpg
TMP = read_pc();
- A ^= read(B|TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
eor_ce_zpx
TMP = read_pc();
- A ^= read(B|uint8_t(TMP+X));
+ PC++;
+ TMP2 = read(B|uint8_t(TMP+X));
+ A ^= TMP2;
set_nz(A);
prefetch();
inc_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2++;
set_nz(TMP2);
@@ -656,7 +783,9 @@ inc_ce_aba
inc_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
TMP2 = read(TMP);
TMP2++;
@@ -671,6 +800,7 @@ inc_ce_acc
inc_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2++;
set_nz(TMP2);
@@ -679,6 +809,7 @@ inc_ce_zpg
inc_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2++;
@@ -688,6 +819,7 @@ inc_ce_zpx
inw_zpg
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
@@ -720,7 +852,9 @@ inz_imp
jmp_ce_iax
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
PC = read(TMP);
PC = set_h(PC, read(TMP+1));
@@ -728,28 +862,34 @@ jmp_ce_iax
jmp_ce_ind
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
PC = set_h(PC, read(TMP+1));
prefetch();
jsr_ce_adr
TMP = read_pc();
+ PC++;
write(SP, PC>>8);
dec_SP_ce();
write(SP, PC);
dec_SP_ce();
TMP = set_h(TMP, read_pc());
+ PC++;
PC = TMP;
prefetch();
jsr_iax
TMP = read_pc();
+ PC++;
write(SP, PC>>8);
dec_SP_ce();
write(SP, PC);
dec_SP_ce();
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
PC = set_h(PC, read(TMP+1));
PC += X;
@@ -757,31 +897,38 @@ jsr_iax
jsr_ind
TMP = read_pc();
+ PC++;
write(SP, PC>>8);
dec_SP_ce();
write(SP, PC);
dec_SP_ce();
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
PC = set_h(PC, read(TMP+1));
prefetch();
lda_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
A = read(TMP + X);
set_nz(A);
prefetch();
lda_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
A = read(TMP + Y);
set_nz(A);
prefetch();
lda_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
@@ -792,6 +939,7 @@ lda_ce_idx
lda_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
@@ -801,6 +949,7 @@ lda_ce_idy
lda_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
@@ -809,8 +958,9 @@ lda_idz
prefetch();
lda_isy
- read_pc_noinc();
+ read_pc();
TMP = read_pc();
+ PC++;
if(P & F_E)
TMP = set_l(SP, SP+TMP);
else
@@ -824,38 +974,46 @@ lda_isy
lda_ce_zpg
TMP = read_pc();
+ PC++;
A = read(B|TMP);
set_nz(A);
prefetch();
lda_ce_zpx
TMP = read_pc();
+ PC++;
A = read(B|uint8_t(TMP+X));
set_nz(A);
prefetch();
ldx_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
X = read(TMP + Y);
set_nz(X);
prefetch();
ldx_ce_zpg
TMP = read_pc();
+ PC++;
X = read(B|TMP);
set_nz(X);
prefetch();
ldx_ce_zpy
TMP = read_pc();
+ PC++;
X = read(B|uint8_t(TMP+Y));
set_nz(X);
prefetch();
ldy_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
Y = read(TMP);
set_nz(Y);
@@ -863,38 +1021,47 @@ ldy_ce_abx
ldy_ce_zpg
TMP = read_pc();
+ PC++;
Y = read(B|TMP);
set_nz(Y);
prefetch();
ldy_ce_zpx
TMP = read_pc();
+ PC++;
Y = read(B|uint8_t(TMP+X));
set_nz(Y);
prefetch();
ldz_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
Z = read(TMP);
set_nz(Z);
prefetch();
ldz_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
Z = read(TMP + X);
set_nz(Z);
prefetch();
ldz_imm
Z = read_pc();
+ PC++;
set_nz(Z);
prefetch();
lsr_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2 = do_lsr(TMP2);
write(TMP, TMP2);
@@ -902,7 +1069,9 @@ lsr_ce_aba
lsr_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -916,6 +1085,7 @@ lsr_ce_acc
lsr_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 = do_lsr(TMP2);
write(TMP, TMP2);
@@ -923,6 +1093,7 @@ lsr_ce_zpg
lsr_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2 = do_lsr(TMP2);
@@ -930,148 +1101,168 @@ lsr_ce_zpx
prefetch();
neg_acc
- read_pc_noinc();
+ read_pc();
A = -A;
set_nz(A);
prefetch();
ora_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A |= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- A |= read(TMP+Z);
+ TMP2 = read(TMP+Z);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_ce_zpg
TMP = read_pc();
- A |= read(B|TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_ce_zpx
TMP = read_pc();
- A |= read(B|uint8_t(TMP+X));
+ PC++;
+ TMP2 = read(B|uint8_t(TMP+X));
+ A |= TMP2;
set_nz(A);
prefetch();
# push/pop instructions and rti/rtn/rts are not fully streamlined
pha_ce_imp
- read_pc_noinc();
+ read_pc();
write(SP, A);
dec_SP_ce();
prefetch();
php_ce_imp
- read_pc_noinc();
+ read_pc();
write(SP, P);
dec_SP_ce();
prefetch();
phw_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP3 = read(TMP);
TMP3 = set_h(TMP3, read(TMP+1));
- dec_SP_ce();
write(SP, TMP3);
dec_SP_ce();
write(SP, TMP3 >> 8);
+ dec_SP_ce();
prefetch();
phw_iw2
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- dec_SP_ce();
+ PC++;
write(SP, TMP);
dec_SP_ce();
write(SP, TMP >> 8);
+ dec_SP_ce();
prefetch();
phx_ce_imp
- read_pc_noinc();
+ read_pc();
write(SP, X);
dec_SP_ce();
prefetch();
phy_ce_imp
- read_pc_noinc();
+ read_pc();
write(SP, Y);
dec_SP_ce();
prefetch();
phz_imp
- read_pc_noinc();
+ read_pc();
write(SP, Z);
dec_SP_ce();
prefetch();
pla_ce_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
A = read(SP);
set_nz(A);
prefetch();
plp_ce_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
TMP = read(SP) | F_B;
prefetch();
P = TMP; // Do *not* move it before the prefetch
plx_ce_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
X = read(SP);
set_nz(X);
prefetch();
ply_ce_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
Y = read(SP);
set_nz(Y);
prefetch();
plz_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
Z = read(SP);
set_nz(Z);
@@ -1079,6 +1270,7 @@ plz_imp
rmb_ce_bzp
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 &= ~(1 << ((inst_state >> 4) & 7));
write(TMP, TMP2);
@@ -1086,7 +1278,9 @@ rmb_ce_bzp
rol_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2 = do_rol(TMP2);
write(TMP, TMP2);
@@ -1094,7 +1288,9 @@ rol_ce_aba
rol_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
TMP2 = read(TMP);
TMP2 = do_rol(TMP2);
@@ -1107,6 +1303,7 @@ rol_ce_acc
rol_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 = do_rol(TMP2);
write(TMP, TMP2);
@@ -1114,6 +1311,7 @@ rol_ce_zpg
rol_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2 = do_rol(TMP2);
@@ -1122,7 +1320,9 @@ rol_ce_zpx
ror_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
TMP2 = do_ror(TMP2);
write(TMP, TMP2);
@@ -1130,7 +1330,9 @@ ror_ce_aba
ror_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
TMP2 = read(TMP);
TMP2 = do_ror(TMP2);
@@ -1143,6 +1345,7 @@ ror_ce_acc
ror_ce_zpg
TMP = B|read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 = do_ror(TMP2);
write(TMP, TMP2);
@@ -1150,6 +1353,7 @@ ror_ce_zpg
ror_ce_zpx
TMP = read_pc();
+ PC++;
TMP = B|uint8_t(TMP+X);
TMP2 = read(TMP);
TMP2 = do_ror(TMP2);
@@ -1158,7 +1362,9 @@ ror_ce_zpx
row_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP3 = read(TMP);
TMP3 = set_h(TMP3, read(TMP+1));
TMP2 = P;
@@ -1177,7 +1383,7 @@ row_aba
prefetch();
rti_ce_imp
- read_pc_noinc();
+ read_pc();
inc_SP_ce();
P = read(SP) | F_B;
inc_SP_ce();
@@ -1188,17 +1394,19 @@ rti_ce_imp
rtn_imm
TMP = read_pc();
+ PC++;
if(P & F_E)
SP = set_l(SP, SP+TMP);
else
SP += TMP;
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
PC = read(SP);
inc_SP();
PC = set_h(PC, read(SP));
read_pc();
+ PC++;
prefetch();
rts_ce_imp
@@ -1207,70 +1415,84 @@ rts_ce_imp
inc_SP_ce();
PC = set_h(PC, read(SP));
read_pc();
+ PC++;
prefetch();
sbc_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += X;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP += Y;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_sbc(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_sbc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
- do_sbc(read(TMP+Z));
+ TMP2 = read(TMP+Z);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_imm
TMP = read_pc();
+ PC++;
do_sbc(TMP);
if(P & F_D)
set_nz(A);
@@ -1278,17 +1500,19 @@ sbc_ce_imm
sbc_ce_zpg
TMP = read_pc();
- TMP = read(B|TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(B|TMP);
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
sbc_ce_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(B|uint8_t(TMP+X));
- do_sbc(TMP);
+ TMP2 = read(B|uint8_t(TMP+X));
+ do_sbc(TMP2);
if(P & F_D)
set_nz(A);
prefetch();
@@ -1302,7 +1526,7 @@ sed_ce_imp
prefetch();
see_imp
- read_pc_noinc();
+ read_pc();
P |= F_E;
prefetch();
@@ -1312,6 +1536,7 @@ sei_ce_imp
smb_ce_bzp
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
TMP2 |= 1 << ((inst_state >> 4) & 7);
write(TMP, TMP2);
@@ -1319,18 +1544,23 @@ smb_ce_bzp
sta_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+X, A);
prefetch();
sta_ce_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+Y, A);
prefetch();
sta_ce_idx
TMP2 = read_pc();
+ PC++;
TMP2 += X;
TMP = read(B|TMP2);
TMP2++;
@@ -1340,6 +1570,7 @@ sta_ce_idx
sta_ce_idy
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
@@ -1348,6 +1579,7 @@ sta_ce_idy
sta_idz
TMP2 = read_pc();
+ PC++;
TMP = read(B|TMP2);
TMP2++;
TMP = set_h(TMP, read(B|TMP2));
@@ -1355,8 +1587,9 @@ sta_idz
prefetch();
sta_isy
- read_pc_noinc();
+ read_pc();
TMP = read_pc();
+ PC++;
if(P & F_E)
TMP = set_l(SP, SP+TMP);
else
@@ -1369,65 +1602,81 @@ sta_isy
sta_ce_zpg
TMP = read_pc();
+ PC++;
write(B|TMP, A);
prefetch();
sta_ce_zpx
TMP = read_pc();
+ PC++;
write(B|uint8_t(TMP+X), A);
prefetch();
stx_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+Y, X);
prefetch();
stx_ce_zpg
TMP = read_pc();
+ PC++;
write(B|TMP, X);
prefetch();
stx_ce_zpy
TMP = read_pc();
+ PC++;
write(B|uint8_t(TMP+Y), X);
prefetch();
sty_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+X, Y);
prefetch();
sty_ce_zpg
TMP = read_pc();
+ PC++;
write(B|TMP, Y);
prefetch();
sty_ce_zpx
TMP = read_pc();
+ PC++;
write(B|uint8_t(TMP+X), Y);
prefetch();
stz_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- write(TMP, A);
+ PC++;
+ write(TMP, Z);
prefetch();
stz_ce_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- write(TMP+X, A);
+ PC++;
+ write(TMP+X, Z);
prefetch();
stz_ce_zpg
TMP = read_pc();
+ PC++;
write(B|TMP, Z);
prefetch();
stz_ce_zpx
TMP = read_pc();
+ PC++;
write(B|uint8_t(TMP+X), Z);
prefetch();
@@ -1457,7 +1706,9 @@ tba_imp
trb_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
if(A & TMP2)
P &= ~F_Z;
@@ -1469,6 +1720,7 @@ trb_ce_aba
trb_ce_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
if(A & TMP2)
P &= ~F_Z;
@@ -1480,7 +1732,9 @@ trb_ce_zpg
tsb_ce_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
if(A & TMP2)
P &= ~F_Z;
@@ -1492,6 +1746,7 @@ tsb_ce_aba
tsb_ce_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
if(A & TMP2)
P &= ~F_Z;
diff --git a/src/devices/cpu/m6502/om740.lst b/src/devices/cpu/m6502/om740.lst
index 34652361335..e37506ae164 100644
--- a/src/devices/cpu/m6502/om740.lst
+++ b/src/devices/cpu/m6502/om740.lst
@@ -2,26 +2,40 @@
# copyright-holders:Olivier Galibert
# m740 opcodes
set_imp
- read_pc_noinc();
+ read_pc();
P |= F_T;
inst_state_base = 0x100;
prefetch();
clt_imp
- read_pc_noinc();
+ read_pc();
P &= ~F_T;
inst_state_base = 0;
prefetch();
ldm_imz
TMP = read_pc();
+ PC++;
TMP2 = read_pc();
+ PC++;
write(TMP2, TMP);
prefetch();
+dec_acc
+ read_pc();
+ A--;
+ set_nz(A);
+ prefetch();
+
+inc_acc
+ read_pc();
+ A++;
+ set_nz(A);
+ prefetch();
+
jsr_spg
- TMP = read_pc_noinc();
- read(SP);
+ TMP = read_pc();
+ read_dummy(SP);
write(SP, PC>>8);
dec_SP();
write(SP, PC);
@@ -31,78 +45,131 @@ jsr_spg
prefetch();
clb_bac
- read_pc_noinc();
+ read_pc();
A = do_clb(A, (IR>>5) & 7);
prefetch();
seb_bac
- read_pc_noinc();
+ read_pc();
A = do_seb(A, (IR>>5) & 7);
prefetch();
clb_biz
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
+ read_dummy(TMP);
TMP2 = do_clb(TMP2, (IR>>5) & 7);
write(TMP, TMP2);
prefetch();
seb_biz
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
+ read_dummy(TMP);
TMP2 = do_seb(TMP2, (IR>>5) & 7);
write(TMP, TMP2);
prefetch();
bbc_bzr
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
- TMP = read_pc();
- read_pc_noinc();
+ read_pc();
if(!(TMP2 & (1 << ((IR>>5) & 7)))) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
}
prefetch();
bbs_bzr
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
- TMP = read_pc();
- read_pc_noinc();
+ read_pc();
if(TMP2 & (1 << ((IR>>5) & 7))) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
}
prefetch();
bbc_bar
- TMP = read_pc();
- read_pc_noinc();
+ read_pc();
+ read_pc();
if(!(A & (1 << ((IR>>5) & 7)))) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
}
prefetch();
bbs_bar
- TMP = read_pc();
- read_pc_noinc();
+ read_pc();
+ read_pc();
if(A & (1 << ((IR>>5) & 7))) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
}
prefetch();
+com_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 ^= 0xff;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
rrf_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
+ read_dummy(TMP);
+ read_dummy(TMP);
+ read_dummy(TMP);
+ read_dummy(TMP);
TMP2 = do_rrf(TMP2);
write(TMP, TMP2);
prefetch();
+tst_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ set_nz(TMP2);
+ prefetch();
+
bra_rel
TMP = read_pc();
- read_pc_noinc();
- if(page_changing(PC, int8_t(TMP))) {
- read_arg(set_l(PC, PC+int8_t(TMP)));
- }
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
PC += int8_t(TMP);
prefetch();
@@ -113,18 +180,53 @@ jmp_zpi
PC = TMP;
prefetch();
-reset740
- P |= F_I; PC = read_arg(0xfffe);
+jsr_zpi
+ TMP2 = read_pc();
+ read_dummy(SP);
+ write(SP, PC>>8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ PC = TMP;
+ prefetch();
+
+stp_imp
+ read_pc();
+ logerror("STP at $%04x\n", PC);
+ while(!irq_state) {
+ eat-all-cycles;
+ }
+ prefetch();
+
+wit_imp
+ read_pc();
+ logerror("WIT at $%04x\n", PC);
+ while(!irq_state) {
+ eat-all-cycles;
+ }
+ prefetch();
+
+reset_m
+ P |= F_I;
+ read_dummy(SP);
+ dec_SP();
+ read_dummy(SP);
+ dec_SP();
+ read_dummy(SP);
+ dec_SP();
+ PC = read_arg(0xfffe);
PC = set_h(PC, read_arg(0xffff));
prefetch();
inst_state = -1;
-brk740_imp
- // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
+brk_m_imp
if(irq_taken) {
- read_pc_noinc();
+ read_pc();
} else {
read_pc();
+ PC++;
}
write(SP, PC >> 8);
dec_SP();
@@ -132,620 +234,1654 @@ brk740_imp
dec_SP();
write(SP, irq_taken ? P & ~F_B : P);
dec_SP();
- if(nmi_state) {
- PC = read_arg(0xfffa);
- PC = set_h(PC, read_arg(0xfffb));
- nmi_state = false;
- standard_irq_callback(NMI_LINE);
- } else {
- PC = read_arg(m_irq_vector);
- PC = set_h(PC, read_arg(m_irq_vector+1));
- if(irq_taken)
- standard_irq_callback(IRQ_LINE);
- }
+ // BRK uses the vector of the interrupt with the highest priority if any are enabled and pending
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
+ PC = read_arg(m_irq_vector);
+ PC = set_h(PC, read_arg(m_irq_vector+1));
irq_taken = false;
P |= F_I; // Do *not* move after the prefetch
prefetch();
inst_state = -1;
+# 6502 opcodes with modified access patterns
+
+adc_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
+ prefetch();
+
+adc_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
+ prefetch();
+
+adc_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ do_adc(TMP2);
+ prefetch();
+
+adc_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ do_adc(TMP2);
+ prefetch();
+
+adc_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ do_adc(TMP2);
+ prefetch();
+
+and_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+and_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+and_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+and_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+and_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+asl_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+bcc_m_rel
+ if(!(P & F_C)) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bcs_m_rel
+ if(P & F_C) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+beq_m_rel
+ if(P & F_Z) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bmi_m_rel
+ if(P & F_N) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bne_m_rel
+ if(!(P & F_Z)) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bpl_m_rel
+ if(!(P & F_N)) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bvc_m_rel
+ if(!(P & F_V)) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+bvs_m_rel
+ if(P & F_V) {
+ TMP = read_pc();
+ read_dummy(set_l(PC, PC+1));
+ PC++;
+ read_dummy(set_l(PC, PC+int8_t(TMP)));
+ PC += int8_t(TMP);
+ } else {
+ read_pc();
+ PC++;
+ }
+ prefetch();
+
+cmp_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
+ prefetch();
+
+cmp_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
+ prefetch();
+
+cmp_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ do_cmp(A, TMP2);
+ prefetch();
+
+cmp_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ do_cmp(A, TMP2);
+ prefetch();
+
+cmp_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ do_cmp(A, TMP2);
+ prefetch();
+
+dec_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+eor_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+eor_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+eor_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+eor_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+eor_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+inc_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+jmp_m_ind
+ // JMP ($XXFF) has the same bug as on the NMOS 6502
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ PC = read_data(TMP);
+ PC = set_h(PC, read_data(set_l(TMP, TMP+1)));
+ prefetch();
+
+jsr_m_adr
+ TMP = read_pc();
+ PC++;
+ read_dummy(SP);
+ write(SP, PC>>8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ PC = TMP;
+ prefetch();
+
+lda_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ A = read(TMP + X);
+ set_nz(A);
+ prefetch();
+
+lda_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ A = read(TMP + Y);
+ set_nz(A);
+ prefetch();
+
+lda_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A = read_data(TMP);
+ set_nz(A);
+ prefetch();
+
+lda_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ A = read_data(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+lda_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ A = read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+ldx_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ X = read(TMP + Y);
+ set_nz(X);
+ prefetch();
+
+ldx_m_zpy
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ X = read(uint8_t(TMP+Y));
+ set_nz(X);
+ prefetch();
+
+ldy_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ Y = read(TMP);
+ set_nz(Y);
+ prefetch();
+
+ldy_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ Y = read(uint8_t(TMP+X));
+ set_nz(Y);
+ prefetch();
+
+lsr_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ora_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+ora_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+ora_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+ora_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+ora_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+pla_m_imp
+ read_pc();
+ read_dummy(SP);
+ inc_SP();
+ A = read(SP);
+ set_nz(A);
+ prefetch();
+
+plp_m_imp
+ read_pc();
+ read_dummy(SP);
+ inc_SP();
+ TMP = read(SP) | (F_B);
+ inst_state_base = (TMP & F_T) ? 0x100 : 0;
+ prefetch();
+ P = TMP; // Do *not* move it before the prefetch
+
+rol_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_m_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read_dummy(TMP);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rti_m_imp
+ read_pc();
+ read_dummy(SP);
+ inc_SP();
+ P = read(SP) | (F_B);
+ inst_state_base = (P & F_T) ? 0x100 : 0;
+ inc_SP();
+ PC = read(SP);
+ inc_SP();
+ PC = set_h(PC, read(SP));
+ prefetch();
+
+rts_m_imp
+ read_pc();
+ read_dummy(SP);
+ inc_SP();
+ PC = read(SP);
+ inc_SP();
+ PC = set_h(PC, read(SP));
+ read_dummy(PC);
+ PC++;
+ prefetch();
+
+sbc_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
+ prefetch();
+
+sbc_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
+ prefetch();
+
+sbc_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read_data(TMP);
+ do_sbc(TMP2);
+ prefetch();
+
+sbc_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ do_sbc(TMP2);
+ prefetch();
+
+sbc_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ do_sbc(TMP2);
+ prefetch();
+
+sta_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(TMP);
+ write(TMP, A);
+ prefetch();
+
+sta_m_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ read_dummy(TMP+X);
+ write(TMP+X, A);
+ prefetch();
+
+sta_m_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ read_dummy(TMP+Y);
+ write(TMP+Y, A);
+ prefetch();
+
+sta_m_idx
+ TMP2 = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(TMP);
+ write_data(TMP, A);
+ prefetch();
+
+sta_m_idy
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_dummy(set_l(TMP, TMP+Y));
+ read_dummy(TMP+Y);
+ write_data(TMP+Y, A);
+ prefetch();
+
+sta_m_zpg
+ TMP = read_pc();
+ PC++;
+ read_dummy(TMP);
+ write(TMP, A);
+ prefetch();
+
+sta_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ read_dummy(uint8_t(TMP+X));
+ write(uint8_t(TMP+X), A);
+ prefetch();
+
+stx_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(TMP);
+ write(TMP, X);
+ prefetch();
+
+stx_m_zpg
+ TMP = read_pc();
+ PC++;
+ read_dummy(TMP);
+ write(TMP, X);
+ prefetch();
+
+stx_m_zpy
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ read_dummy(uint8_t(TMP+Y));
+ write(uint8_t(TMP+Y), X);
+ prefetch();
+
+sty_m_aba
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read_dummy(TMP);
+ write(TMP, Y);
+ prefetch();
+
+sty_m_zpg
+ TMP = read_pc();
+ PC++;
+ read_dummy(TMP);
+ write(TMP, Y);
+ prefetch();
+
+sty_m_zpx
+ TMP = read_pc();
+ read_dummy(PC & 0xff);
+ PC++;
+ read_dummy(uint8_t(TMP+X));
+ write(uint8_t(TMP+X), Y);
+ prefetch();
+
# T=1 opcodes
adct_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP = read(TMP);
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP = read(TMP);
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- do_adct(read(TMP));
- write(X, TMP2);
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- do_adct(read(TMP+Y));
- write(X, TMP2);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_imm
- TMP = read_pc();
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_zpg
TMP = read_pc();
- TMP = read(TMP);
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
adct_zpx
TMP = read_pc();
- read(TMP);
- TMP = read(uint8_t(TMP+X));
- TMP2 = read(X);
- do_adct(TMP);
- write(X, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ read_dummy(X);
+ do_adct(TMP2);
+ write(X, TMP);
prefetch();
andt_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP2 = read(X);
- TMP2 &= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP2 = read(X);
- TMP2 &= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP2 = read(X);
- TMP2 &= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_imm
+ TMP = read_pc();
+ PC++;
TMP2 = read(X);
- TMP2 &= read_pc();
+ read_dummy(X);
+ TMP2 &= TMP;
set_nz(TMP2);
write(X, TMP2);
prefetch();
andt_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- TMP2 &= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- TMP2 &= read(TMP+Y);
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_zpg
TMP = read_pc();
- TMP2 = read(X);
- TMP2 &= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
andt_zpx
TMP = read_pc();
- read(TMP);
- TMP2 = read(X);
- TMP2 &= read(uint8_t(TMP+X));
- set_nz(TMP2);
- write(X, TMP2);
- prefetch();
-
-com_zpg
- TMP = read_pc();
- TMP2 = read(TMP);
- TMP2 ^= 0xff;
- set_nz(TMP2);
- write(TMP, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ read_dummy(X);
+ TMP &= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
cmpt_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- TMP2 = read(X);
- do_cmp(TMP2, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP = read(TMP);
- TMP2 = read(X);
- do_cmp(TMP2, TMP);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP = read(TMP);
- TMP2 = read(X);
- do_cmp(TMP2, TMP);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- do_cmp(TMP2, read(TMP));
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- do_cmp(TMP2, read(TMP+Y));
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_imm
TMP = read_pc();
+ PC++;
TMP2 = read(X);
do_cmp(TMP2, TMP);
prefetch();
cmpt_zpg
TMP = read_pc();
- TMP = read(TMP);
- TMP2 = read(X);
- do_cmp(TMP2, TMP);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
cmpt_zpx
TMP = read_pc();
- read(TMP);
- TMP = read(uint8_t(TMP+X));
- TMP2 = read(X);
- do_cmp(TMP2, TMP);
- prefetch();
-
-dec_acc
- read_pc_noinc();
- A--;
- set_nz(A);
- prefetch();
-
-dect_acc
- read_pc_noinc();
- TMP2 = read(X);
- TMP2--;
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ do_cmp(TMP, TMP2);
prefetch();
eort_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP2 = read(X);
- TMP2 ^= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP2 = read(X);
- TMP2 ^= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP2 = read(X);
- TMP2 ^= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- TMP2 ^= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- TMP2 ^= read(TMP+Y);
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_imm
+ TMP = read_pc();
+ PC++;
TMP2 = read(X);
- TMP2 ^= read_pc();
+ read_dummy(X);
+ TMP2 ^= TMP;
set_nz(TMP2);
write(X, TMP2);
prefetch();
eort_zpg
TMP = read_pc();
- TMP2 = read(X);
- TMP2 ^= read(TMP+Y);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
eort_zpx
TMP = read_pc();
- read(TMP);
- TMP2 = read(X);
- TMP2 ^= read(uint8_t(TMP+X));
- set_nz(TMP2);
- write(X, TMP2);
- prefetch();
-
-inc_acc
- read_pc_noinc();
- A++;
- set_nz(A);
- prefetch();
-
-inct_acc
- read_pc_noinc();
- TMP2 = read(X);
- TMP2++;
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ read_dummy(X);
+ TMP ^= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ldt_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
- TMP2 = read(TMP + X);
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(TMP + Y);
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(TMP);
+ TMP2 = read_data(TMP);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(TMP+Y);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_imm
TMP2 = read_pc();
+ PC++;
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ldt_zpx
TMP = read_pc();
- read(TMP);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 = read(uint8_t(TMP+X));
+ read_dummy(X);
set_nz(TMP2);
write(X, TMP2);
prefetch();
ort_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP2 = read(X);
- TMP2 |= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP2 = read(X);
- TMP2 |= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP2 = read(X);
- TMP2 |= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_imm
+ TMP = read_pc();
+ PC++;
TMP2 = read(X);
- TMP2 |= read_pc();
+ read_dummy(X);
+ TMP2 |= TMP;
set_nz(TMP2);
write(X, TMP2);
prefetch();
ort_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- TMP2 |= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- TMP2 |= read(TMP+Y);
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_zpg
TMP = read_pc();
- TMP2 = read(X);
- TMP2 |= read(TMP);
- set_nz(TMP2);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
ort_zpx
TMP = read_pc();
- read(TMP);
- TMP2 = read(X);
- TMP2 |= read(uint8_t(TMP+X));
- set_nz(TMP2);
- write(X, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ read_dummy(X);
+ TMP |= TMP2;
+ set_nz(TMP);
+ write(X, TMP);
prefetch();
sbct_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, X)) {
- read(set_l(TMP, TMP+X));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+X));
TMP += X;
- TMP = read(TMP);
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
+ PC++;
+ read_dummy(set_l(TMP, TMP+Y));
TMP += Y;
- TMP = read(TMP);
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_idx
TMP2 = read_pc();
- read(TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- TMP2 = read(X);
- do_sbct(read(TMP));
- write(X, TMP2);
+ TMP2 = read_data(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- if(page_changing(TMP, Y)) {
- read(set_l(TMP, TMP+Y));
- }
- TMP2 = read(X);
- do_sbct(read(TMP+Y));
- write(X, TMP2);
+ read_dummy(set_l(TMP, TMP+Y));
+ TMP2 = read_data(TMP+Y);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_imm
- TMP = read_pc();
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_zpg
TMP = read_pc();
- TMP = read(TMP);
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
sbct_zpx
TMP = read_pc();
- read(TMP);
- TMP = read(uint8_t(TMP+X));
- TMP2 = read(X);
- do_sbct(TMP);
- write(X, TMP2);
+ read_dummy(PC & 0xff);
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ TMP = read(X);
+ read_dummy(X);
+ do_sbct(TMP2);
+ write(X, TMP);
prefetch();
diff --git a/src/devices/cpu/m6502/or65c19.lst b/src/devices/cpu/m6502/or65c19.lst
new file mode 100644
index 00000000000..36568280df8
--- /dev/null
+++ b/src/devices/cpu/m6502/or65c19.lst
@@ -0,0 +1,488 @@
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert, AJR
+adc_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ prefetch();
+
+add_imm
+ TMP = read_pc();
+ PC++;
+ do_add(TMP);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ prefetch();
+
+add_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ do_add(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ prefetch();
+
+add_zpx
+ TMP = read_pc();
+ PC++;
+ read(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_add(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ prefetch();
+
+and_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+asr_acc
+ read_pc();
+ A = do_asr(A);
+ prefetch();
+
+bar_amr
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 = ~TMP2 & TMP;
+ TMP = read_pc();
+ PC++;
+ if(TMP2 != 0) {
+ read_pc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bas_amr
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 &= TMP;
+ TMP = read_pc();
+ PC++;
+ if(TMP2 != 0) {
+ read_pc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+brk_r_imp
+ if(irq_taken || nmi_pending) {
+ read_pc();
+ } else {
+ read_pc();
+ PC++;
+ }
+ write(SP, PC >> 8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
+ dec_SP();
+ if(irq_taken && nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
+ PC = read_arg(0xfffc);
+ PC = set_h(PC, read_arg(0xfffd));
+ nmi_pending = false;
+ } else {
+ if(irq_taken)
+ standard_irq_callback(((~TMP & 0x000e) >> 1) - 1, PC);
+ TMP = get_irq_vector();
+ PC = read_arg(TMP);
+ PC = set_h(PC, read_arg(TMP+1));
+ }
+ irq_taken = false;
+ P = (P | F_I) & ~F_D; // Do *not* move after the prefetch
+ prefetch();
+ inst_state = -1;
+
+clw_imp
+ read_pc();
+ P &= ~F_V;
+ m_w = 0;
+ prefetch();
+
+cmp_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ do_cmp(A, TMP2);
+ prefetch();
+
+eor_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+exc_zpx
+ TMP = read_pc();
+ PC++;
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, A);
+ A = TMP2;
+ prefetch();
+
+ini_imp
+ read_pc();
+ read(m_i);
+ m_i++;
+ prefetch();
+
+jpi_ind
+ m_i = PC;
+ TMP = read_arg(m_i);
+ TMP = set_h(TMP, read_arg(m_i+1));
+ m_i += 2;
+ PC = read(TMP);
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+jsb_vec
+ read_pc();
+ write(SP, PC>>8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ TMP = 0xffe0 | ((inst_state >> 3) & 0x0e);
+ PC = read_arg(TMP);
+ PC = set_h(PC, read_arg(TMP+1));
+ prefetch();
+
+jmp_r_ind
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ PC = read(TMP);
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+jsr_r_adr
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ write(SP, PC>>8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ PC = TMP;
+ prefetch();
+
+lab_acc
+ read_pc();
+ read_pc();
+ if(int8_t(A) < 0)
+ A = -A;
+ set_nz(A);
+ prefetch();
+
+lai_imp
+ read_pc();
+ A = read(m_i);
+ prefetch();
+
+lan_imp
+ read_pc();
+ A = read(m_i);
+ m_i++;
+ prefetch();
+
+lda_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ A = read(TMP+X);
+ set_nz(A);
+ prefetch();
+
+lii_imp
+ read_pc();
+ TMP = read(m_i);
+ TMP = set_h(TMP, read(m_i+1));
+ read(TMP);
+ m_i = TMP;
+ prefetch();
+
+mpa_imp
+ read_pc();
+ read_pc();
+ read_pc();
+ read_pc();
+ read_pc();
+ TMP = int8_t(A) * int8_t(Y);
+ m_w = do_accumulate(TMP, m_w);
+ prefetch();
+
+mpy_imp
+ read_pc();
+ read_pc();
+ read_pc();
+ read_pc();
+ read_pc();
+ TMP = int8_t(A) * int8_t(Y);
+ A = do_accumulate(TMP, 0)>>8;
+ prefetch();
+
+neg_acc
+ read_pc();
+ A = -A;
+ set_nz(A);
+ prefetch();
+
+nxt_imp
+ read_pc();
+ PC = read(m_i);
+ PC = set_h(PC, read(m_i+1));
+ m_i += 2;
+ prefetch();
+
+ora_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+phi_imp
+ read_pc();
+ write(SP, m_i>>8);
+ dec_SP();
+ write(SP, m_i);
+ dec_SP();
+ prefetch();
+
+phw_imp
+ read_pc();
+ write(SP, m_w>>8);
+ dec_SP();
+ write(SP, m_w);
+ dec_SP();
+ prefetch();
+
+pia_imp
+ read_pc();
+ read(SP);
+ inc_SP();
+ m_i = read(SP);
+ inc_SP();
+ m_i = set_h(m_i, read(SP));
+ A = read(m_i);
+ m_i++;
+ prefetch();
+
+pli_imp
+ read_pc();
+ read(SP);
+ inc_SP();
+ m_i = read(SP);
+ inc_SP();
+ m_i = set_h(m_i, read(SP));
+ read(m_i);
+ prefetch();
+
+plw_imp
+ read_pc();
+ read(SP);
+ inc_SP();
+ m_w = read(SP);
+ inc_SP();
+ m_w = set_h(m_w, read(SP));
+ prefetch();
+
+psh_imp
+ read_pc();
+ write(SP, A);
+ dec_SP();
+ write(SP, X);
+ dec_SP();
+ write(SP, Y);
+ dec_SP();
+ prefetch();
+
+pul_imp
+ read_pc();
+ read(SP);
+ inc_SP();
+ Y = read(SP);
+ inc_SP();
+ X = read(SP);
+ inc_SP();
+ A = read(SP);
+ prefetch();
+
+rba_ima
+ A = read_pc(); // "Note that Accumulator contents are altered by RBA and SBA" (C29/C39 Technical Reference Manual, p. C-29)
+ PC++;
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read(TMP);
+ TMP2 &= ~A;
+ write(TMP, TMP2);
+ prefetch();
+
+rnd_imp
+ read_pc();
+ TMP = set_l(m_w, Y);
+ A = do_accumulate(TMP, (m_w<<1) & 0x100)>>8;
+ prefetch();
+
+rts_r_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ PC = read(SP);
+ inc_SP();
+ PC = set_h(PC, read(SP));
+ prefetch();
+
+sba_ima
+ A = read_pc();
+ PC++;
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP2 = read(TMP);
+ read(TMP);
+ TMP2 |= A;
+ write(TMP, TMP2);
+ prefetch();
+
+sbc_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP2 = read(TMP+X);
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ prefetch();
+
+sta_ipx
+ TMP2 = read_pc();
+ PC++;
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+X));
+ write(TMP+X, A);
+ prefetch();
+
+sti_imz
+ TMP = read_pc();
+ PC++;
+ TMP2 = read_pc();
+ PC++;
+ write(TMP2, TMP);
+ prefetch();
+
+taw_imp
+ read_pc();
+ m_w = A<<8;
+ set_nz(m_w>>8);
+ prefetch();
+
+tip_imp
+ read_pc();
+ PC = m_i;
+ prefetch();
+
+twa_imp
+ read_pc();
+ A = m_w>>8;
+ set_nz(A);
+ prefetch();
+
+# exceptions
+reset_r
+ read_pc();
+ PC++;
+ read_pc();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ P = (P | F_I) & ~F_D;
+ PC = read_arg(0xfffe);
+ PC = set_h(PC, read_arg(0xffff));
+ prefetch();
+ inst_state = -1;
diff --git a/src/devices/cpu/m6502/on2a03.lst b/src/devices/cpu/m6502/orp2a03.lst
index 096c5f08211..44f453a1c4e 100644
--- a/src/devices/cpu/m6502/on2a03.lst
+++ b/src/devices/cpu/m6502/orp2a03.lst
@@ -1,80 +1,97 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
-# n2a03 opcodes - same as 6502 but with d disabled
+# rp2a03 opcodes - same as 6502 but with d disabled
adc_nd_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_adc_nd(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_adc_nd(TMP);
+ TMP2 = read(TMP);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_adc_nd(TMP);
+ TMP2 = read(TMP);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_adc_nd(read(TMP));
+ TMP2 = read(TMP);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_adc_nd(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_imm
TMP = read_pc();
+ PC++;
do_adc_nd(TMP);
prefetch();
adc_nd_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_adc_nd(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc_nd(TMP2);
prefetch();
adc_nd_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_adc_nd(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_adc_nd(TMP2);
prefetch();
arr_nd_imm
- A &= read_pc();
+ TMP = read_pc();
+ A &= TMP;
+ PC++;
do_arr_nd();
prefetch();
rra_nd_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -84,7 +101,9 @@ rra_nd_aba
rra_nd_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -96,7 +115,9 @@ rra_nd_abx
rra_nd_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -108,6 +129,7 @@ rra_nd_aby
rra_nd_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -121,6 +143,7 @@ rra_nd_idx
rra_nd_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -134,6 +157,7 @@ rra_nd_idy
rra_nd_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_ror(TMP2);
@@ -143,6 +167,7 @@ rra_nd_zpg
rra_nd_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -154,73 +179,88 @@ rra_nd_zpx
sbc_nd_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_sbc_nd(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_sbc_nd(TMP);
+ TMP2 = read(TMP);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_sbc_nd(TMP);
+ TMP2 = read(TMP);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_sbc_nd(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_sbc_nd(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_imm
TMP = read_pc();
+ PC++;
do_sbc_nd(TMP);
prefetch();
sbc_nd_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_sbc_nd(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc_nd(TMP2);
prefetch();
sbc_nd_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_sbc_nd(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_sbc_nd(TMP2);
prefetch();
isb_nd_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -230,7 +270,9 @@ isb_nd_aba
isb_nd_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -242,7 +284,9 @@ isb_nd_abx
isb_nd_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+Y));
TMP += Y;
TMP2 = read(TMP);
@@ -254,6 +298,7 @@ isb_nd_aby
isb_nd_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
@@ -267,6 +312,7 @@ isb_nd_idx
isb_nd_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y));
@@ -280,6 +326,7 @@ isb_nd_idy
isb_nd_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2++;
@@ -289,6 +336,7 @@ isb_nd_zpg
isb_nd_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
diff --git a/src/devices/cpu/m6502/om65c02.lst b/src/devices/cpu/m6502/ow65c02.lst
index d5428557344..d4debf9f1fc 100644
--- a/src/devices/cpu/m6502/om65c02.lst
+++ b/src/devices/cpu/m6502/ow65c02.lst
@@ -1,127 +1,146 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
-# m65c02 opcodes
+# w65c02 opcodes
adc_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_adc(TMP);
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_adc(read(TMP));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_adc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_imm
TMP = read_pc();
+ PC++;
do_adc(TMP);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_adc(read(TMP));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
adc_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_adc(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_adc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
and_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
asl_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_asl(TMP2);
@@ -130,7 +149,9 @@ asl_c_aba
asl_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -141,6 +162,7 @@ asl_c_abx
asl_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_asl(TMP2);
@@ -149,6 +171,7 @@ asl_c_zpg
asl_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -159,36 +182,52 @@ asl_c_zpx
bbr_zpb
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP = read_pc();
+ PC++;
if(!(TMP2 & (1 << ((inst_state >> 4) & 7)))) {
+ read_pc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
PC += int8_t(TMP);
}
prefetch();
bbs_zpb
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP = read_pc();
+ PC++;
if(TMP2 & (1 << ((inst_state >> 4) & 7))) {
+ read_pc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
PC += int8_t(TMP);
}
prefetch();
bit_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- do_bit(read(TMP));
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bit_imm
TMP = read_pc();
+ PC++;
if(A & TMP)
P &= ~F_Z;
else
@@ -197,14 +236,16 @@ bit_imm
bit_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_bit(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_bit(TMP2);
prefetch();
bra_rel
TMP = read_pc();
- read_pc_noinc();
+ PC++;
+ read_pc();
if(page_changing(PC, int8_t(TMP))) {
read_arg(set_l(PC, PC+int8_t(TMP)));
}
@@ -212,27 +253,28 @@ bra_rel
prefetch();
brk_c_imp
- if(irq_taken || nmi_state) {
- read_pc_noinc();
+ if(irq_taken || nmi_pending) {
+ read_pc();
} else {
read_pc();
+ PC++;
}
write(SP, PC >> 8);
dec_SP();
write(SP, PC);
dec_SP();
- write(SP, irq_taken || nmi_state ? P & ~F_B : P);
+ write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
dec_SP();
- if(irq_taken && nmi_state) {
+ if(irq_taken && nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb));
- nmi_state = false;
- standard_irq_callback(NMI_LINE);
+ nmi_pending = false;
} else {
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
PC = read_arg(0xfffe);
PC = set_h(PC, read_arg(0xffff));
- if(irq_taken)
- standard_irq_callback(IRQ_LINE);
}
irq_taken = false;
P = (P | F_I) & ~F_D; // Do *not* move after the prefetch
@@ -241,20 +283,24 @@ brk_c_imp
cmp_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_cmp(A, read(TMP));
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
dec_acc
- read_pc_noinc();
+ read_pc();
A--;
set_nz(A);
prefetch();
dec_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2--;
@@ -264,7 +310,9 @@ dec_c_aba
dec_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -276,6 +324,7 @@ dec_c_abx
dec_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2--;
@@ -285,6 +334,7 @@ dec_c_zpg
dec_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -296,21 +346,25 @@ dec_c_zpx
eor_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
inc_acc
- read_pc_noinc();
+ read_pc();
A++;
set_nz(A);
prefetch();
inc_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2++;
@@ -320,7 +374,9 @@ inc_c_aba
inc_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -332,6 +388,7 @@ inc_c_abx
inc_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2++;
@@ -341,6 +398,7 @@ inc_c_zpg
inc_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -352,7 +410,9 @@ inc_c_zpx
jmp_iax
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
PC = read(TMP);
@@ -361,7 +421,9 @@ jmp_iax
jmp_c_ind
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
read(set_l(TMP, TMP+1));
PC = set_h(PC, read(TMP+1));
@@ -369,6 +431,7 @@ jmp_c_ind
lda_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
A = read(TMP);
@@ -377,7 +440,9 @@ lda_zpi
lsr_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_lsr(TMP2);
@@ -386,7 +451,9 @@ lsr_c_aba
lsr_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -397,6 +464,7 @@ lsr_c_abx
lsr_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_lsr(TMP2);
@@ -405,6 +473,7 @@ lsr_c_zpg
lsr_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -418,42 +487,48 @@ nop_c_imp
nop_c_aba
read_pc();
+ PC++;
+ read_pc();
+ PC++;
+ read_pc();
+ read_pc();
+ read_pc();
+ read_pc();
read_pc();
- read_pc_noinc();
- read_pc_noinc();
- read_pc_noinc();
- read_pc_noinc();
- read_pc_noinc();
prefetch();
nop_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
prefetch();
ora_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
phx_imp
- read_pc_noinc();
+ read_pc();
write(SP, X);
dec_SP();
prefetch();
phy_imp
- read_pc_noinc();
+ read_pc();
write(SP, Y);
dec_SP();
prefetch();
plx_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
X = read(SP);
@@ -461,7 +536,7 @@ plx_imp
prefetch();
ply_imp
- read_pc_noinc();
+ read_pc();
read(SP);
inc_SP();
Y = read(SP);
@@ -470,6 +545,7 @@ ply_imp
rmb_bzp
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 &= ~(1 << ((inst_state >> 4) & 7));
@@ -478,7 +554,9 @@ rmb_bzp
rol_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_rol(TMP2);
@@ -487,7 +565,9 @@ rol_c_aba
rol_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -498,6 +578,7 @@ rol_c_abx
rol_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_rol(TMP2);
@@ -506,6 +587,7 @@ rol_c_zpg
rol_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -516,7 +598,9 @@ rol_c_zpx
ror_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_ror(TMP2);
@@ -525,7 +609,9 @@ ror_c_aba
ror_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
TMP += X;
TMP2 = read(TMP);
@@ -536,6 +622,7 @@ ror_c_abx
ror_c_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 = do_ror(TMP2);
@@ -544,6 +631,7 @@ ror_c_zpg
ror_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
TMP = uint8_t(TMP+X);
TMP2 = read(TMP);
@@ -554,115 +642,131 @@ ror_c_zpx
sbc_c_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
- TMP = read(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, X)) {
read(set_l(TMP, TMP+X));
}
TMP += X;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
TMP += Y;
- TMP = read(TMP);
- do_sbc(TMP);
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_idx
TMP2 = read_pc();
+ PC++;
read(TMP2);
TMP2 += X;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_sbc(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_idy
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y));
}
- do_sbc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_imm
TMP = read_pc();
+ PC++;
do_sbc(TMP);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_zpg
TMP = read_pc();
- TMP = read(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
- do_sbc(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
sbc_c_zpx
TMP = read_pc();
+ PC++;
read(TMP);
- TMP = read(uint8_t(TMP+X));
- do_sbc(TMP);
+ TMP2 = read(uint8_t(TMP+X));
+ do_sbc(TMP2);
if(P & F_D) {
- read_pc_noinc();
+ read_pc();
set_nz(A);
}
prefetch();
smb_bzp
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
read(TMP);
TMP2 |= 1 << ((inst_state >> 4) & 7);
@@ -671,6 +775,7 @@ smb_bzp
sta_zpi
TMP2 = read_pc();
+ PC++;
TMP = read(TMP2 & 0xff);
TMP = set_h(TMP, read((TMP2+1) & 0xff));
write(TMP, A);
@@ -683,33 +788,41 @@ stp_imp
stz_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP, 0x00);
prefetch();
stz_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
read(set_l(TMP, TMP+X));
write(TMP+X, 0x00);
prefetch();
stz_zpg
TMP = read_pc();
+ PC++;
write(TMP, 0x00);
prefetch();
stz_zpx
TMP = read_pc();
+ PC++;
read(TMP);
write(uint8_t(TMP+X), 0x00);
prefetch();
trb_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
- write(TMP, TMP2);
+ read(TMP);
if(A & TMP2)
P &= ~F_Z;
else
@@ -720,8 +833,9 @@ trb_aba
trb_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
- write(TMP, TMP2);
+ read(TMP);
if(A & TMP2)
P &= ~F_Z;
else
@@ -732,9 +846,11 @@ trb_zpg
tsb_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
- write(TMP, TMP2);
+ read(TMP);
if(A & TMP2)
P &= ~F_Z;
else
@@ -745,8 +861,9 @@ tsb_aba
tsb_zpg
TMP = read_pc();
+ PC++;
TMP2 = read(TMP);
- write(TMP, TMP2);
+ read(TMP);
if(A & TMP2)
P &= ~F_Z;
else
@@ -756,9 +873,9 @@ tsb_zpg
prefetch();
wai_imp
- read_pc_noinc();
- read_pc_noinc();
- while(!nmi_state && !irq_state) {
+ read_pc();
+ read_pc();
+ while(!nmi_pending && !irq_state) {
eat-all-cycles;
}
prefetch();
@@ -766,10 +883,13 @@ wai_imp
# exceptions
reset_c
read_arg(0xffff);
- read_pc_noinc();
- read(SP); dec_SP();
- read(SP); dec_SP();
- read(SP); dec_SP();
+ read_pc();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
P = (P | F_I) & ~F_D;
PC = read_arg(0xfffc);
PC = set_h(PC, read_arg(0xfffd));
diff --git a/src/devices/cpu/m6502/ow65c02s.lst b/src/devices/cpu/m6502/ow65c02s.lst
new file mode 100644
index 00000000000..5e6f5a346cb
--- /dev/null
+++ b/src/devices/cpu/m6502/ow65c02s.lst
@@ -0,0 +1,968 @@
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# w65c02s opcodes
+
+adc_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+adc_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+adc_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+adc_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+adc_s_zpx
+ TMP = read_pc();
+ read_pc();
+ TMP2 = read(uint8_t(TMP+X));
+ do_adc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+and_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ A &= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+and_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ A &= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+and_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+and_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ A &= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+and_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+asl_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP+1);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+asl_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+bit_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ do_bit(TMP2);
+ PC++;
+ prefetch();
+
+bit_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ do_bit(TMP2);
+ prefetch();
+
+brk_s_imp
+ if(irq_taken || nmi_pending) {
+ read_pc();
+ } else {
+ read_pc();
+ PC++;
+ }
+ write(SP, PC >> 8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
+ dec_SP();
+ if(irq_taken && nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
+ PC = read_vector(0xfffa);
+ PC = set_h(PC, read_vector(0xfffb));
+ nmi_pending = false;
+ } else {
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
+ PC = read_vector(0xfffe);
+ PC = set_h(PC, read_vector(0xffff));
+ }
+ irq_taken = false;
+ P = (P | F_I) & ~F_D; // Do *not* move after the prefetch
+ prefetch();
+ inst_state = -1;
+
+cmp_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
+ PC++;
+ prefetch();
+
+cmp_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
+ PC++;
+ prefetch();
+
+cmp_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
+ prefetch();
+
+cmp_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ do_cmp(A, TMP2);
+ PC++;
+ prefetch();
+
+cmp_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = read(uint8_t(TMP+X));
+ do_cmp(A, TMP);
+ prefetch();
+
+dec_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP+1);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+dec_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+eor_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+eor_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+eor_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+eor_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ A ^= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+eor_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+inc_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP+1);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+inc_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+jmp_s_iax
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ read_pc();
+ TMP += X;
+ PC = read(TMP);
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+jmp_s_ind
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ read_pc();
+ PC = read(TMP);
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+lda_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ A = read(TMP + X);
+ set_nz(A);
+ PC++;
+ prefetch();
+
+lda_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ A = read(TMP + Y);
+ set_nz(A);
+ PC++;
+ prefetch();
+
+lda_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lda_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ A = read(TMP+Y);
+ set_nz(A);
+ PC++;
+ prefetch();
+
+lda_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ A = read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+ldx_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ X = read(TMP + Y);
+ set_nz(X);
+ PC++;
+ prefetch();
+
+ldx_s_zpy
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ X = read(uint8_t(TMP+Y));
+ set_nz(X);
+ prefetch();
+
+ldy_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ Y = read(TMP);
+ set_nz(Y);
+ PC++;
+ prefetch();
+
+ldy_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ Y = read(uint8_t(TMP+X));
+ set_nz(Y);
+ prefetch();
+
+lsr_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+lsr_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+nop_s_abx
+ read_pc();
+ PC++;
+ read_pc();
+ read_pc();
+ PC++;
+ prefetch();
+
+nop_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ read(uint8_t(TMP+X));
+ prefetch();
+
+ora_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ A |= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+ora_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ A |= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+ora_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+ora_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ A |= TMP2;
+ set_nz(A);
+ PC++;
+ prefetch();
+
+ora_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP2 = read(uint8_t(TMP+X));
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+pla_s_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ A = read(SP);
+ set_nz(A);
+ prefetch();
+
+plp_s_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ TMP = read(SP) | (F_B|F_E);
+ prefetch();
+ P = TMP; // Do *not* move it before the prefetch
+
+plx_s_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ X = read(SP);
+ set_nz(X);
+ prefetch();
+
+ply_s_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ Y = read(SP);
+ set_nz(Y);
+ prefetch();
+
+rol_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP+1);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+rol_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP+1);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ PC++;
+ prefetch();
+
+ror_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rti_s_imp
+ read_pc();
+ inc_SP();
+ P = read(SP) | (F_B|F_E);
+ inc_SP();
+ TMP = read(SP);
+ inc_SP();
+ TMP = set_h(TMP, read(SP));
+ read_pc();
+ end_interrupt();
+ PC = TMP;
+ prefetch();
+
+rts_s_imp
+ read_pc();
+ read_pc();
+ inc_SP();
+ TMP = read(SP);
+ inc_SP();
+ TMP = set_h(TMP, read(SP));
+ read_pc();
+ PC = TMP + 1;
+ prefetch();
+
+sbc_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read_pc();
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+sbc_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP += Y;
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+sbc_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+sbc_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read_pc();
+ }
+ TMP2 = read(TMP+Y);
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+sbc_s_zpx
+ TMP = read_pc();
+ read_pc();
+ TMP2 = read(uint8_t(TMP+X));
+ do_sbc(TMP2);
+ if(P & F_D) {
+ read_pc();
+ set_nz(A);
+ }
+ PC++;
+ prefetch();
+
+sta_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ read_pc();
+ PC++;
+ write(TMP+X, A);
+ prefetch();
+
+sta_s_aby
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ read_pc();
+ PC++;
+ write(TMP+Y, A);
+ prefetch();
+
+sta_s_idx
+ TMP2 = read_pc();
+ read_pc();
+ PC++;
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ write(TMP, A);
+ prefetch();
+
+sta_s_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read_pc();
+ PC++;
+ write(TMP+Y, A);
+ prefetch();
+
+sta_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ write(uint8_t(TMP+X), A);
+ prefetch();
+
+stx_s_zpy
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ write(uint8_t(TMP+Y), X);
+ prefetch();
+
+sty_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ write(uint8_t(TMP+X), Y);
+ prefetch();
+
+stz_s_abx
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ read_pc();
+ PC++;
+ write(TMP+X, 0x00);
+ prefetch();
+
+stz_s_zpx
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ write(uint8_t(TMP+X), 0x00);
+ prefetch();
+
+trb_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 &= ~A;
+ write(TMP, TMP2);
+ prefetch();
+
+tsb_s_zpg
+ TMP = read_pc();
+ PC++;
+ TMP2 = read(TMP);
+ read((TMP+1) & 0xff);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 |= A;
+ write(TMP, TMP2);
+ prefetch();
+
+# exceptions
+reset_s
+ read_arg(0xffff);
+ read_pc();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ read(SP);
+ dec_SP();
+ P = (P | F_I) & ~F_D;
+ PC = read_vector(0xfffc);
+ PC = set_h(PC, read_vector(0xfffd));
+ prefetch();
+ inst_state = -1;
diff --git a/src/devices/cpu/m6502/oxavix.lst b/src/devices/cpu/m6502/oxavix.lst
index 0f1f60e4221..84caf0a2277 100644
--- a/src/devices/cpu/m6502/oxavix.lst
+++ b/src/devices/cpu/m6502/oxavix.lst
@@ -4,50 +4,58 @@
callf_xa3
read_stack(SP);
- write_special_stack(get_codebank());
+ write_special_stack(SP, get_codebank());
dec_special_stack();
TMP2 = read_pc();
+ PC++;
TMP = read_pc();
+ PC++;
//read_stack(SP);
write_stack(SP, PC>>8);
dec_SP();
write_stack(SP, PC);
dec_SP();
TMP = set_h(TMP, read_pc());
+ PC++;
PC = TMP;
set_codebank(TMP2);
prefetch();
jmp_xa3
TMP2 = read_pc();
+ PC++;
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
PC = TMP;
set_codebank(TMP2);
prefetch();
retf_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
PC = read_stack(SP);
inc_SP();
PC = set_h(PC, read_stack(SP));
inc_special_stack();
- TMP2 = read_special_stack();
+ TMP2 = read_special_stack(SP);
set_codebank(TMP2);
read_pc();
+ PC++;
prefetch();
brk_xav_imp
- // there is code in soem games to indicate this doesn't always push the far bank to the stack..
- // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
+ // there is code in some games to indicate this doesn't always push the far bank to the stack..
+ // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending)
if(irq_taken) {
- read_pc_noinc();
+ read_pc();
} else {
read_pc();
+ PC++;
}
- write_special_stack(get_codebank());
+ write_special_stack(SP, get_codebank());
set_codebank(0x00); // epo_efdx, rad_ping and rad_mtrk strongly suggest that interrupts must force bank 0 as code jumps to a ROM pointer stored earlier / a fixed pointer to a rom address in bank 0
dec_special_stack();
write_stack(SP, PC >> 8);
@@ -56,7 +64,8 @@ brk_xav_imp
dec_SP();
write_stack(SP, irq_taken ? P & ~F_B : P);
dec_SP();
- if(nmi_state) {
+ if(nmi_pending) {
+ standard_irq_callback(NMI_LINE, PC);
if (m_vector_callback.isnull())
{
PC = read_arg(0xfffa);
@@ -76,9 +85,10 @@ brk_xav_imp
}
}
- nmi_state = false;
- standard_irq_callback(NMI_LINE);
+ nmi_pending = false;
} else {
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE, PC);
if (m_vector_callback.isnull())
{
PC = read_arg(0xfffe);
@@ -97,9 +107,6 @@ brk_xav_imp
PC = set_h(PC, read_arg(0xffff));
}
}
-
- if(irq_taken)
- standard_irq_callback(IRQ_LINE);
}
irq_taken = false;
P |= F_I; // Do *not* move after the prefetch
@@ -107,7 +114,7 @@ brk_xav_imp
inst_state = -1;
rti_xav_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
P = read_stack(SP) | (F_B|F_E);
@@ -116,7 +123,7 @@ rti_xav_imp
inc_SP();
PC = set_h(PC, read_stack(SP));
inc_special_stack();
- TMP2 = read_special_stack();
+ TMP2 = read_special_stack(SP);
set_codebank(TMP2);
prefetch();
@@ -124,30 +131,32 @@ rti_xav_imp
# opcodes below are modified to access stack through different handlers
pha_xav_imp
- read_pc_noinc();
+ read_pc();
write_stack(SP, A);
dec_SP();
prefetch();
php_xav_imp
- read_pc_noinc();
+ read_pc();
write_stack(SP, P);
dec_SP();
prefetch();
jsr_xav_adr
TMP = read_pc();
+ PC++;
read_stack(SP);
write_stack(SP, PC>>8);
dec_SP();
write_stack(SP, PC);
dec_SP();
TMP = set_h(TMP, read_pc());
+ PC++;
PC = TMP;
prefetch();
pla_xav_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
A = read_stack(SP);
@@ -155,7 +164,7 @@ pla_xav_imp
prefetch();
plp_xav_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
TMP = read_stack(SP) | (F_B|F_E);
@@ -163,13 +172,14 @@ plp_xav_imp
P = TMP; // Do *not* move it before the prefetch
rts_xav_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
PC = read_stack(SP);
inc_SP();
PC = set_h(PC, read_stack(SP));
read_pc();
+ PC++;
prefetch();
# opcodes below are modified to access zero page through different handlers
@@ -177,6 +187,7 @@ rts_xav_imp
lda_xav_idy
TMP2 = read_pc(); // we need to fetch the zero page part from zero page, but the rest as if zero page wasn't there, similar to the 6509
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
@@ -188,108 +199,129 @@ lda_xav_idy
adc_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- do_adc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_adc(TMP2);
prefetch();
cmp_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- do_cmp(A, read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_cmp(A, TMP2);
prefetch();
sbc_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- do_sbc(read(TMP+Y));
+ TMP2 = read(TMP+Y);
+ do_sbc(TMP2);
prefetch();
eor_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- A ^= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A ^= TMP2;
set_nz(A);
prefetch();
and_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- A &= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A &= TMP2;
set_nz(A);
prefetch();
ora_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
read(set_l(TMP, TMP+Y)); // dummy read
}
- A |= read(TMP+Y);
+ TMP2 = read(TMP+Y);
+ A |= TMP2;
set_nz(A);
prefetch();
ora_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- A |= read(TMP);
+ TMP2 = read(TMP);
+ A |= TMP2;
set_nz(A);
prefetch();
and_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- A &= read(TMP);
+ TMP2 = read(TMP);
+ A &= TMP2;
set_nz(A);
prefetch();
eor_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- A ^= read(TMP);
+ TMP2 = read(TMP);
+ A ^= TMP2;
set_nz(A);
prefetch();
adc_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- do_adc(read(TMP));
+ TMP2 = read(TMP);
+ do_adc(TMP2);
prefetch();
lda_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -300,24 +332,29 @@ lda_xav_idx
cmp_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- do_cmp(A, read(TMP));
+ TMP2 = read(TMP);
+ do_cmp(A, TMP2);
prefetch();
sbc_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
- do_sbc(read(TMP));
+ TMP2 = read(TMP);
+ do_sbc(TMP2);
prefetch();
sta_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read_zeropage(set_l(TMP, TMP+Y)); // dummy read
@@ -326,6 +363,7 @@ sta_xav_idy
sta_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -335,18 +373,21 @@ sta_xav_idx
adc_xav_zpg
TMP = read_pc();
- TMP = read_zeropage(TMP);
- do_adc(TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_adc(TMP2);
prefetch();
and_xav_zpg
TMP = read_pc();
+ PC++;
A &= read_zeropage(TMP);
set_nz(A);
prefetch();
asl_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_asl(TMP2);
@@ -355,29 +396,34 @@ asl_xav_zpg
bit_xav_zpg
TMP = read_pc();
+ PC++;
do_bit(read_zeropage(TMP));
prefetch();
cmp_xav_zpg
TMP = read_pc();
- TMP = read_zeropage(TMP);
- do_cmp(A, TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_cmp(A, TMP2);
prefetch();
cpx_xav_zpg
TMP = read_pc();
- TMP = read_zeropage(TMP);
- do_cmp(X, TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_cmp(X, TMP2);
prefetch();
cpy_xav_zpg
TMP = read_pc();
- TMP = read_zeropage(TMP);
- do_cmp(Y, TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_cmp(Y, TMP2);
prefetch();
dec_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2--;
@@ -387,12 +433,14 @@ dec_xav_zpg
eor_xav_zpg
TMP = read_pc();
+ PC++;
A ^= read_zeropage(TMP);
set_nz(A);
prefetch();
inc_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2++;
@@ -402,24 +450,28 @@ inc_xav_zpg
lda_xav_zpg
TMP = read_pc();
+ PC++;
A = read_zeropage(TMP);
set_nz(A);
prefetch();
ldx_xav_zpg
TMP = read_pc();
+ PC++;
X = read_zeropage(TMP);
set_nz(X);
prefetch();
ldy_xav_zpg
TMP = read_pc();
+ PC++;
Y = read_zeropage(TMP);
set_nz(Y);
prefetch();
lsr_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_lsr(TMP2);
@@ -428,12 +480,14 @@ lsr_xav_zpg
ora_xav_zpg
TMP = read_pc();
+ PC++;
A |= read_zeropage(TMP);
set_nz(A);
prefetch();
rol_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_rol(TMP2);
@@ -442,6 +496,7 @@ rol_xav_zpg
ror_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_ror(TMP2);
@@ -450,27 +505,32 @@ ror_xav_zpg
sbc_xav_zpg
TMP = read_pc();
- TMP = read_zeropage(TMP);
- do_sbc(TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_sbc(TMP2);
prefetch();
sta_xav_zpg
TMP = read_pc();
+ PC++;
write_zeropage(TMP, A);
prefetch();
stx_xav_zpg
TMP = read_pc();
+ PC++;
write_zeropage(TMP, X);
prefetch();
sty_xav_zpg
TMP = read_pc();
+ PC++;
write_zeropage(TMP, Y);
prefetch();
dcp_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2--;
@@ -480,6 +540,7 @@ dcp_xav_zpg
isb_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2++;
@@ -489,12 +550,14 @@ isb_xav_zpg
lax_xav_zpg
TMP = read_pc();
+ PC++;
A = X = read_zeropage(TMP);
set_nz(A);
prefetch();
rla_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_rol(TMP2);
@@ -505,6 +568,7 @@ rla_xav_zpg
rra_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_ror(TMP2);
@@ -514,12 +578,14 @@ rra_xav_zpg
sax_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = A & X;
write_zeropage(TMP, TMP2);
prefetch();
slo_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_asl(TMP2);
@@ -530,6 +596,7 @@ slo_xav_zpg
sre_xav_zpg
TMP = read_pc();
+ PC++;
TMP2 = read_zeropage(TMP);
write_zeropage(TMP, TMP2); // dummy write
TMP2 = do_lsr(TMP2);
@@ -540,6 +607,7 @@ sre_xav_zpg
nop_xav_zpg
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
prefetch();
@@ -547,6 +615,7 @@ nop_xav_zpg
ldx_xav_zpy
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
X = read_zeropage(uint8_t(TMP+Y));
set_nz(X);
@@ -554,12 +623,14 @@ ldx_xav_zpy
stx_xav_zpy
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
write_zeropage(uint8_t(TMP+Y), X);
prefetch();
lax_xav_zpy
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+Y);
A = X = read_zeropage(TMP);
@@ -568,7 +639,8 @@ lax_xav_zpy
sax_xav_zpy
TMP = read_pc();
- read_zeropage(TMP); // dummy reaad
+ PC++;
+ read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+Y);
TMP2 = A & X;
write_zeropage(TMP, TMP2);
@@ -578,13 +650,15 @@ sax_xav_zpy
adc_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
- TMP = read_zeropage(uint8_t(TMP+X));
- do_adc(TMP);
+ TMP2 = read_zeropage(uint8_t(TMP+X));
+ do_adc(TMP2);
prefetch();
and_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
A &= read_zeropage(uint8_t(TMP+X));
set_nz(A);
@@ -592,6 +666,7 @@ and_xav_zpx
asl_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -602,13 +677,15 @@ asl_xav_zpx
cmp_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
- TMP = read_zeropage(uint8_t(TMP+X));
- do_cmp(A, TMP);
+ TMP2 = read_zeropage(uint8_t(TMP+X));
+ do_cmp(A, TMP2);
prefetch();
dec_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -620,6 +697,7 @@ dec_xav_zpx
eor_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
A ^= read_zeropage(uint8_t(TMP+X));
set_nz(A);
@@ -627,6 +705,7 @@ eor_xav_zpx
inc_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -638,6 +717,7 @@ inc_xav_zpx
lda_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
A = read_zeropage(uint8_t(TMP+X));
set_nz(A);
@@ -645,6 +725,7 @@ lda_xav_zpx
ldy_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
Y = read_zeropage(uint8_t(TMP+X));
set_nz(Y);
@@ -652,6 +733,7 @@ ldy_xav_zpx
lsr_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -662,6 +744,7 @@ lsr_xav_zpx
ora_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
A |= read_zeropage(uint8_t(TMP+X));
set_nz(A);
@@ -669,6 +752,7 @@ ora_xav_zpx
rol_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -679,6 +763,7 @@ rol_xav_zpx
ror_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -689,25 +774,29 @@ ror_xav_zpx
sbc_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
- TMP = read_zeropage(uint8_t(TMP+X));
- do_sbc(TMP);
+ TMP2 = read_zeropage(uint8_t(TMP+X));
+ do_sbc(TMP2);
prefetch();
sta_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
write_zeropage(uint8_t(TMP+X), A);
prefetch();
sty_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
write_zeropage(uint8_t(TMP+X), Y);
prefetch();
dcp_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -719,6 +808,7 @@ dcp_xav_zpx
isb_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -730,6 +820,7 @@ isb_xav_zpx
rla_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -742,6 +833,7 @@ rla_xav_zpx
rra_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -753,6 +845,7 @@ rra_xav_zpx
slo_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -765,6 +858,7 @@ slo_xav_zpx
sre_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP); // dummy read
TMP = uint8_t(TMP+X);
TMP2 = read_zeropage(TMP);
@@ -777,6 +871,7 @@ sre_xav_zpx
nop_xav_zpx
TMP = read_pc();
+ PC++;
read_zeropage(TMP);
read_zeropage(uint8_t(TMP+X));
prefetch();
@@ -785,6 +880,7 @@ nop_xav_zpx
slo_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -801,6 +897,7 @@ slo_xav_idx
rla_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -815,6 +912,7 @@ rla_xav_idx
sre_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -829,6 +927,7 @@ sre_xav_idx
rra_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -842,6 +941,7 @@ rra_xav_idx
sax_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -852,6 +952,7 @@ sax_xav_idx
lax_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dumm read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -862,6 +963,7 @@ lax_xav_idx
dcp_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -875,6 +977,7 @@ dcp_xav_idx
isb_xav_idx
TMP2 = read_pc();
+ PC++;
read_zeropage(TMP2); // dummy read
TMP2 += X;
TMP = read_zeropage(TMP2 & 0xff);
@@ -890,6 +993,7 @@ isb_xav_idx
slo_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -904,6 +1008,7 @@ slo_xav_idy
rla_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -918,6 +1023,7 @@ rla_xav_idy
sre_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -932,6 +1038,7 @@ sre_xav_idy
rra_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -945,6 +1052,7 @@ rra_xav_idy
sha_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -958,6 +1066,7 @@ sha_xav_idy
lax_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
if(page_changing(TMP, Y)) {
@@ -969,6 +1078,7 @@ lax_xav_idy
dcp_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
@@ -982,6 +1092,7 @@ dcp_xav_idy
isb_xav_idy
TMP2 = read_pc();
+ PC++;
TMP = read_zeropage(TMP2);
TMP = set_h(TMP, read_zeropage((TMP2+1) & 0xff));
read(set_l(TMP, TMP+Y)); // dummy read
diff --git a/src/devices/cpu/m6502/oxavix2000.lst b/src/devices/cpu/m6502/oxavix2000.lst
index a457c651418..ec61ee4067a 100644
--- a/src/devices/cpu/m6502/oxavix2000.lst
+++ b/src/devices/cpu/m6502/oxavix2000.lst
@@ -3,19 +3,19 @@
# xavix2000 opcodes (Super XaviX)
phy_imp
- read_pc_noinc();
+ read_pc();
write_stack(SP, Y);
dec_SP();
prefetch();
phx_imp
- read_pc_noinc();
+ read_pc();
write_stack(SP, X);
dec_SP();
prefetch();
plx_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
X = read_stack(SP);
@@ -23,7 +23,7 @@ plx_imp
prefetch();
ply_imp
- read_pc_noinc();
+ read_pc();
read_stack(SP);
inc_SP();
Y = read_stack(SP);
@@ -31,314 +31,316 @@ ply_imp
prefetch();
clr_acc
- read_pc_noinc();
+ read_pc();
A = 0;
set_nz(A);
prefetch();
dec_acc
- read_pc_noinc();
+ read_pc();
A--;
set_nz(A);
prefetch();
not_acc
- read_pc_noinc();
+ read_pc();
A = A ^ 0xff;
set_nz(A);
prefetch();
inc_acc
- read_pc_noinc();
+ read_pc();
A++;
set_nz(A);
prefetch();
neg_acc
- read_pc_noinc();
+ read_pc();
A = (0x00 - A) & 0xff;
set_nz(A);
prefetch();
oraj_imp
- read_pc_noinc();
+ read_pc();
A |= m_j;
set_nz(A);
prefetch();
orak_imp
- read_pc_noinc();
+ read_pc();
A |= m_k;
set_nz(A);
prefetch();
oral_imp
- read_pc_noinc();
+ read_pc();
A |= m_l;
set_nz(A);
prefetch();
oram_imp
- read_pc_noinc();
+ read_pc();
A |= m_m;
set_nz(A);
prefetch();
andj_imp
- read_pc_noinc();
+ read_pc();
A &= m_j;
set_nz(A);
prefetch();
andk_imp
- read_pc_noinc();
+ read_pc();
A &= m_k;
set_nz(A);
prefetch();
andl_imp
- read_pc_noinc();
+ read_pc();
A &= m_l;
set_nz(A);
prefetch();
andm_imp
- read_pc_noinc();
+ read_pc();
A &= m_m;
set_nz(A);
prefetch();
eorj_imp
- read_pc_noinc();
+ read_pc();
A ^= m_j;
set_nz(A);
prefetch();
eork_imp
- read_pc_noinc();
+ read_pc();
A ^= m_k;
set_nz(A);
prefetch();
eorl_imp
- read_pc_noinc();
+ read_pc();
A ^= m_l;
set_nz(A);
prefetch();
eorm_imp
- read_pc_noinc();
+ read_pc();
A ^= m_m;
set_nz(A);
prefetch();
adcj_imp
- read_pc_noinc();
+ read_pc();
do_adc(m_j);
prefetch();
adck_imp
- read_pc_noinc();
+ read_pc();
do_adc(m_k);
prefetch();
adcl_imp
- read_pc_noinc();
+ read_pc();
do_adc(m_l);
prefetch();
adcm_imp
- read_pc_noinc();
+ read_pc();
do_adc(m_m);
prefetch();
staj_imp
- read_pc_noinc();
+ read_pc();
m_j = A;
prefetch();
stak_imp
- read_pc_noinc();
+ read_pc();
m_k = A;
prefetch();
stal_imp
- read_pc_noinc();
+ read_pc();
m_l = A;
prefetch();
stam_imp
- read_pc_noinc();
+ read_pc();
m_m = A;
prefetch();
ldaj_imp
- read_pc_noinc();
+ read_pc();
A = m_j;
set_nz(A);
prefetch();
ldak_imp
- read_pc_noinc();
+ read_pc();
A = m_k;
set_nz(A);
prefetch();
ldal_imp
- read_pc_noinc();
+ read_pc();
A = m_l;
set_nz(A);
prefetch();
ldam_imp
- read_pc_noinc();
+ read_pc();
A = m_m;
set_nz(A);
prefetch();
cmpj_imp
- read_pc_noinc();
+ read_pc();
do_cmp(A, m_j);
prefetch();
cmpk_imp
- read_pc_noinc();
+ read_pc();
do_cmp(A, m_k);
prefetch();
cmpl_imp
- read_pc_noinc();
+ read_pc();
do_cmp(A, m_l);
prefetch();
cmpm_imp
- read_pc_noinc();
+ read_pc();
do_cmp(A, m_m);
prefetch();
sbcj_imp
- read_pc_noinc();
+ read_pc();
do_sbc(m_j);
prefetch();
sbck_imp
- read_pc_noinc();
+ read_pc();
do_sbc(m_k);
prefetch();
sbcl_imp
- read_pc_noinc();
+ read_pc();
do_sbc(m_l);
prefetch();
sbcm_imp
- read_pc_noinc();
+ read_pc();
do_sbc(m_m);
prefetch();
spa0_imp
- read_pc_noinc();
+ read_pc();
m_pa = (m_pa & 0xffff00) | A;
prefetch();
lpa0_imp
- read_pc_noinc();
+ read_pc();
A = (m_pa & 0x0000ff) >> 0;
set_nz(A);
prefetch();
spa1_imp
- read_pc_noinc();
+ read_pc();
m_pa = (m_pa & 0xff00ff) | (A << 8);
prefetch();
lpa1_imp
- read_pc_noinc();
+ read_pc();
A = (m_pa & 0x00ff00) >> 8;
set_nz(A);
prefetch();
spa2_imp
- read_pc_noinc();
+ read_pc();
m_pa = (m_pa & 0x00ffff) | (A << 16);
prefetch();
lpa2_imp
- read_pc_noinc();
+ read_pc();
A = (m_pa & 0xff0000) >> 16;
set_nz(A);
prefetch();
spb0_imp
- read_pc_noinc();
+ read_pc();
m_pb = (m_pb & 0xffff00) | A;
prefetch();
lpb0_imp
- read_pc_noinc();
+ read_pc();
A = (m_pb & 0x0000ff) >> 0;
set_nz(A);
prefetch();
spb1_imp
- read_pc_noinc();
+ read_pc();
m_pb = (m_pb & 0xff00ff) | (A << 8);
prefetch();
lpb1_imp
- read_pc_noinc();
+ read_pc();
A = (m_pb & 0x00ff00) >> 8;
set_nz(A);
prefetch();
spb2_imp
- read_pc_noinc();
+ read_pc();
m_pb = (m_pb & 0x00ffff) | (A << 16);
prefetch();
lpb2_imp
- read_pc_noinc();
+ read_pc();
A = (m_pb & 0xff0000) >> 16;
set_nz(A);
prefetch();
incpa_imp
- read_pc_noinc();
+ read_pc();
m_pa = (m_pa & ~0xff) | ((m_pa+1) & 0xff);
set_nz(m_pa&0xff); // startup code seems to require flag to set if low byte is 0x00?
prefetch();
incpb_imp
- read_pc_noinc();
+ read_pc();
m_pb = (m_pb & ~0xff) | ((m_pb+1) & 0xff);
set_nz(m_pb&0xff); // startup code seems to require flag to set if low byte is 0x00?
prefetch();
decpa_imp
- read_pc_noinc();
+ read_pc();
m_pa = (m_pa & ~0xff) | ((m_pa-1) & 0xff);
set_nz(m_pa&0xff); // startup code seems to require flag to set if low byte is 0x00?
prefetch();
decpb_imp
- read_pc_noinc();
+ read_pc();
m_pb = (m_pb & ~0xff) | ((m_pb-1) & 0xff);
set_nz(m_pb&0xff); // startup code seems to require flag to set if low byte is 0x00?
prefetch();
orapa_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
andpa_imp
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
+ TMP = read_full_data(m_pa);
+ A &= TMP;
+ set_nz(A);
prefetch();
eorpa_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
adcpa_imp
@@ -355,8 +357,8 @@ ldapa_imp
prefetch();
cmppa_imp
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ TMP = read_full_data(m_pa);
+ do_cmp(A, TMP);
prefetch();
sbcpa_imp
@@ -365,17 +367,17 @@ sbcpa_imp
orapb_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
andpb_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
eorpb_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
adcpb_imp
@@ -393,7 +395,7 @@ ldapb_imp
cmppb_imp
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
sbcpb_imp
@@ -402,54 +404,68 @@ sbcpb_imp
stx_aby
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+Y, X);
prefetch();
sty_abx
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP+X, Y);
prefetch();
stz_xav_zpg
TMP = read_pc();
+ PC++;
write_zeropage(TMP, 0x00);
prefetch();
stz_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
write(TMP, 0x00);
prefetch();
bit_xav_zpx
fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
prefetch();
bit_abx
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ TMP += X;
+ TMP2 = read(TMP);
+ do_bit(TMP2);
prefetch();
bit_imm
TMP = read_pc();
- if(A & TMP)
- P &= ~F_Z;
- else
- P |= F_Z;
+ PC++;
+ do_bit(TMP);
prefetch();
asr_xav_zpg
TMP = read_pc(); // TODO: verify this, should it write back or set A?
- TMP = read_zeropage(TMP);
- do_asr(TMP);
+ PC++;
+ TMP2 = read_zeropage(TMP);
+ do_asr(TMP2);
+ write_zeropage(TMP,TMP2);
prefetch();
asr_aba
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
TMP2 = read(TMP);
write(TMP, TMP2);
TMP2 = do_asr(TMP2); // used by xavbox, see 14e8
@@ -457,8 +473,14 @@ asr_aba
prefetch();
asr_xav_zpx
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ TMP = read_pc();
+ read_pc();
+ PC++;
+ TMP = uint8_t(TMP+X);
+ TMP2 = read_zeropage(TMP);
+ read_zeropage((TMP+1) & 0xff);
+ TMP2 = do_asr(TMP2);
+ write_zeropage(TMP, TMP2);
prefetch();
asr_acc
@@ -466,23 +488,36 @@ asr_acc
prefetch();
asr_abx
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ TMP = read_pc();
+ PC++;
+ TMP = set_h(TMP, read_pc());
+ PC++;
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ read(TMP);
+ TMP2 = do_asr(TMP2);
+ write(TMP, TMP2);
prefetch();
cmc_imp
- fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
- read_pc_noinc();
+ read_pc();
+ TMP = P & F_C;
+ P &= ~F_C;
+ TMP = ~TMP;
+ P |= TMP & F_C;
prefetch();
sev_imp
- read_pc_noinc();
+ read_pc();
P |= F_V;
prefetch();
jmpf_ind
TMP = read_pc();
+ PC++;
TMP = set_h(TMP, read_pc());
+ PC++;
PC = read(TMP);
PC = set_h(PC, read(set_l(TMP, TMP+1)));
TMP2 = read(TMP+2);
diff --git a/src/devices/cpu/m6502/r65c02.cpp b/src/devices/cpu/m6502/r65c02.cpp
index 190f370c933..9dc65010c8c 100644
--- a/src/devices/cpu/m6502/r65c02.cpp
+++ b/src/devices/cpu/m6502/r65c02.cpp
@@ -2,9 +2,13 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- r65c02.c
+ r65c02.cpp
Rockwell 65c02, CMOS variant with bitwise instructions
+ Also licensed to Ricoh, who sold it as RP65C02.
+
+ TODO:
+ - are any of the CPU subtype differences meaningful to MAME?
***************************************************************************/
@@ -13,14 +17,26 @@
#include "r65c02d.h"
DEFINE_DEVICE_TYPE(R65C02, r65c02_device, "r65c02", "Rockwell R65C02")
+DEFINE_DEVICE_TYPE(R65C102, r65c102_device, "r65c102", "Rockwell R65C102")
+DEFINE_DEVICE_TYPE(R65C112, r65c112_device, "r65c112", "Rockwell R65C112")
+
+r65c02_device::r65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ w65c02_device(mconfig, type, tag, owner, clock)
+{
+}
r65c02_device::r65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
r65c02_device(mconfig, R65C02, tag, owner, clock)
{
}
-r65c02_device::r65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- m65c02_device(mconfig, type, tag, owner, clock)
+r65c102_device::r65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ r65c02_device(mconfig, R65C102, tag, owner, clock)
+{
+}
+
+r65c112_device::r65c112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ r65c02_device(mconfig, R65C112, tag, owner, clock)
{
}
diff --git a/src/devices/cpu/m6502/r65c02.h b/src/devices/cpu/m6502/r65c02.h
index a28ccd9d932..d9be47465ee 100644
--- a/src/devices/cpu/m6502/r65c02.h
+++ b/src/devices/cpu/m6502/r65c02.h
@@ -11,9 +11,9 @@
#ifndef MAME_CPU_M6502_R65C02_H
#define MAME_CPU_M6502_R65C02_H
-#include "m65c02.h"
+#include "w65c02.h"
-class r65c02_device : public m65c02_device {
+class r65c02_device : public w65c02_device {
public:
r65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -25,6 +25,20 @@ protected:
r65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
};
+class r65c102_device : public r65c02_device {
+public:
+ r65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
+ virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
+};
+
+class r65c112_device : public r65c02_device {
+public:
+ r65c112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
enum {
R65C02_IRQ_LINE = m6502_device::IRQ_LINE,
R65C02_NMI_LINE = m6502_device::NMI_LINE,
@@ -32,5 +46,7 @@ enum {
};
DECLARE_DEVICE_TYPE(R65C02, r65c02_device)
+DECLARE_DEVICE_TYPE(R65C102, r65c102_device)
+DECLARE_DEVICE_TYPE(R65C112, r65c112_device)
#endif // MAME_CPU_M6502_R65C02_H
diff --git a/src/devices/cpu/m6502/r65c19.cpp b/src/devices/cpu/m6502/r65c19.cpp
new file mode 100644
index 00000000000..ffd6c3ee2db
--- /dev/null
+++ b/src/devices/cpu/m6502/r65c19.cpp
@@ -0,0 +1,290 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Rockwell R65C19 Microcomputer (MCU)
+
+ TODO: fully describe this MCU and its successors (C29, C39) and
+ emulate their internal peripherals (only core emulation now)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "r65c19.h"
+#include "r65c19d.h"
+
+DEFINE_DEVICE_TYPE(R65C19, r65c19_device, "r65c19", "Rockwell R65C19 MCU")
+DEFINE_DEVICE_TYPE(L2800, l2800_device, "l2800", "Rockwell L2800 MCU")
+
+r65c19_device::r65c19_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map)
+ : r65c02_device(mconfig, type, tag, owner, clock)
+ , m_w(0)
+ , m_i(0)
+ , m_page1_ram(*this, "page1")
+ , m_cir(0)
+{
+ program_config.m_internal_map = std::move(internal_map);
+}
+
+r65c19_device::r65c19_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : r65c19_device(mconfig, R65C19, tag, owner, clock, address_map_constructor())
+{
+}
+
+c39_device::c39_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map)
+ : r65c19_device(mconfig, type, tag, owner, clock, internal_map)
+ , m_exp_config("expansion", ENDIANNESS_LITTLE, 8, 21, 0)
+ , m_es4_config("es4", ENDIANNESS_LITTLE, 8, 9, 0)
+{
+}
+
+l2800_device::l2800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c39_device(mconfig, L2800, tag, owner, clock, address_map_constructor(FUNC(l2800_device::internal_map), this))
+{
+}
+
+std::unique_ptr<util::disasm_interface> r65c19_device::create_disassembler()
+{
+ return std::make_unique<r65c19_disassembler>();
+}
+
+void r65c19_device::do_add(u8 v)
+{
+ P &= ~F_C;
+ do_adc(v);
+}
+
+u16 r65c19_device::do_accumulate(u16 v, u16 w)
+{
+ // Compute the sum
+ s32 result = s16(v) + s16(w);
+
+ // Determine flags and saturate result upon overflow
+ P &= ~(F_N | F_V);
+ if (result > 32767)
+ {
+ P |= F_V;
+ result = 32767;
+ }
+ else if (result < 0)
+ {
+ P |= F_N;
+ if (result < -32768)
+ {
+ P |= F_V;
+ result = -32768;
+ }
+ }
+
+ // MPA and MPY always destroy the old value of Y, as does RND when it overflows
+ Y = result & 0xff;
+
+ // 16-bit result to W, or high byte to A
+ return result & 0xffff;
+}
+
+u16 r65c19_device::get_irq_vector()
+{
+ // TODO: this is a stub
+ return 0xfffc;
+}
+
+void r65c19_device::device_start()
+{
+ mintf = std::make_unique<mi_default>();
+
+ c19_init();
+}
+
+device_memory_interface::space_config_vector c39_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &program_config),
+ std::make_pair(AS_DATA, &m_exp_config),
+ std::make_pair(AS_IO, &m_es4_config)
+ };
+}
+
+void c39_device::device_start()
+{
+ std::unique_ptr<mi_banked> intf = std::make_unique<mi_banked>();
+ space(AS_DATA).cache(intf->escache);
+ space(AS_DATA).specific(intf->exp);
+ space(AS_IO).specific(intf->es4);
+
+ save_item(NAME(intf->bsr));
+ save_item(NAME(intf->pbs));
+ mintf = std::move(intf);
+
+ c19_init();
+
+ for (int i = 0; i < 8; i++)
+ state_add(C39_BSR0 + i, string_format("BSR%d", i).c_str(), downcast<mi_banked &>(*mintf).bsr[i]);
+}
+
+void r65c19_device::c19_init()
+{
+ init();
+
+ state_add(R65C19_W, "W", m_w);
+ state_add<u8>(R65C19_WL, "WL",
+ [this]() { return m_w & 0xff; },
+ [this](u8 data) { m_w = set_l(m_w, data); }).noshow();
+ state_add<u8>(R65C19_WH, "WH",
+ [this]() { return m_w >> 8; },
+ [this](u8 data) { m_w = set_h(m_w, data); }).noshow();
+ state_add(R65C19_I, "I", m_i);
+
+ save_item(NAME(m_w));
+ save_item(NAME(m_i));
+ save_item(NAME(m_cir));
+}
+
+void r65c19_device::device_reset()
+{
+ r65c02_device::device_reset();
+
+ m_cir = 0x00;
+}
+
+void c39_device::device_reset()
+{
+ r65c02_device::device_reset();
+
+ mi_banked &intf = downcast<mi_banked &>(*mintf);
+ intf.bsr[0] = 0xe0;
+ intf.bsr[1] = 0xd1;
+ intf.bsr[2] = 0xb2;
+ intf.bsr[3] = 0xb3;
+ intf.bsr[4] = 0x74;
+ intf.bsr[5] = 0x75;
+ intf.bsr[6] = 0x76;
+ intf.bsr[7] = 0x77;
+ intf.pbs = 0xff;
+}
+
+u8 r65c19_device::page1_seg_r(offs_t offset)
+{
+ return m_page1_ram[(m_cir & 0x03) << 6 | offset];
+}
+
+void r65c19_device::page1_seg_w(offs_t offset, u8 data)
+{
+ m_page1_ram[(m_cir & 0x03) << 6 | offset] = data;
+}
+
+u8 r65c19_device::cir_r()
+{
+ return m_cir;
+}
+
+void r65c19_device::cir_w(u8 data)
+{
+ // TODO: clear interrupts
+ m_cir = data & 0x07;
+}
+
+u8 c39_device::mi_banked::exp_read(u16 adr)
+{
+ return exp.read_byte(u32(bsr[(adr & 0xe000) >> 13]) << 13 | (adr & 0x1fff));
+}
+
+u8 c39_device::mi_banked::exp_read_cached(u16 adr)
+{
+ return escache.read_byte(u32(bsr[(adr & 0xe000) >> 13]) << 13 | (adr & 0x1fff));
+}
+
+void c39_device::mi_banked::exp_write(u16 adr, u8 val)
+{
+ exp.write_byte(u32(bsr[(adr & 0xe000) >> 13]) << 13 | (adr & 0x1fff), val);
+}
+
+u8 c39_device::mi_banked::es4_read(u16 adr)
+{
+ return es4.read_byte(adr & 0x1ff);
+}
+
+void c39_device::mi_banked::es4_write(u16 adr, u8 val)
+{
+ es4.write_byte(adr & 0x1ff, val);
+}
+
+u8 c39_device::mi_banked::read(u16 adr)
+{
+ return program.read_byte(adr);
+}
+
+u8 c39_device::mi_banked::read_sync(u16 adr)
+{
+ if (adr < 0x0600)
+ return cprogram.read_byte(adr);
+ else if (adr >= 0x0800 || BIT(pbs, 1))
+ return exp_read_cached(adr);
+ else
+ return es4_read(adr);
+}
+
+u8 c39_device::mi_banked::read_arg(u16 adr)
+{
+ if (adr < 0x0600)
+ return cprogram.read_byte(adr);
+ else if (adr >= 0x0800 || BIT(pbs, 1))
+ return exp_read_cached(adr);
+ else
+ return es4_read(adr);
+}
+
+void c39_device::mi_banked::write(u16 adr, u8 val)
+{
+ program.write_byte(adr, val);
+}
+
+u8 c39_device::pbs_r()
+{
+ return downcast<mi_banked &>(*mintf).pbs;
+}
+
+void c39_device::pbs_w(u8 data)
+{
+ downcast<mi_banked &>(*mintf).pbs = data;
+}
+
+u8 c39_device::bsr_r(offs_t offset)
+{
+ return downcast<mi_banked &>(*mintf).bsr[offset];
+}
+
+void c39_device::bsr_w(offs_t offset, u8 data)
+{
+ downcast<mi_banked &>(*mintf).bsr[offset] = data;
+}
+
+u8 c39_device::expansion_r(offs_t offset)
+{
+ mi_banked &intf = downcast<mi_banked &>(*mintf);
+ if (offset >= 0x0200 || BIT(intf.pbs, 1))
+ return intf.exp_read(offset + 0x0600);
+ else
+ return intf.es4_read(offset + 0x0600);
+}
+
+void c39_device::expansion_w(offs_t offset, u8 data)
+{
+ mi_banked &intf = downcast<mi_banked &>(*mintf);
+ if (offset >= 0x0200 || BIT(intf.pbs, 1))
+ intf.exp_write(offset + 0x0600, data);
+ else
+ intf.es4_write(offset + 0x0600, data);
+}
+
+void l2800_device::internal_map(address_map &map)
+{
+ // TODO: most registers still unimplemented
+ map(0x0005, 0x0005).rw(FUNC(l2800_device::pbs_r), FUNC(l2800_device::pbs_w));
+ map(0x000b, 0x000b).rw(FUNC(l2800_device::cir_r), FUNC(l2800_device::cir_w));
+ map(0x0018, 0x001f).rw(FUNC(l2800_device::bsr_r), FUNC(l2800_device::bsr_w));
+ map(0x0040, 0x05fd).ram(); // Page 0 has 192 dedicated bytes here
+ map(0x0600, 0xffff).rw(FUNC(l2800_device::expansion_r), FUNC(l2800_device::expansion_w));
+}
+
+#include "cpu/m6502/r65c19.hxx"
diff --git a/src/devices/cpu/m6502/r65c19.h b/src/devices/cpu/m6502/r65c19.h
new file mode 100644
index 00000000000..7c53a74ecc4
--- /dev/null
+++ b/src/devices/cpu/m6502/r65c19.h
@@ -0,0 +1,165 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_M6502_R65C19_H
+#define MAME_CPU_M6502_R65C19_H
+
+#pragma once
+
+#include "r65c02.h"
+
+class r65c19_device : public r65c02_device
+{
+public:
+ enum {
+ R65C19_W = M6502_IR + 1,
+ R65C19_WL,
+ R65C19_WH,
+ R65C19_I
+ };
+
+ r65c19_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ r65c19_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ virtual void do_exec_full() override;
+ virtual void do_exec_partial() override;
+
+ virtual u16 get_irq_vector();
+
+ void c19_init();
+
+ u8 cir_r();
+ void cir_w(u8 data);
+ u8 page1_seg_r(offs_t offset);
+ void page1_seg_w(offs_t offset, u8 data);
+
+private:
+ void do_add(u8 v);
+ u16 do_accumulate(u16 v, u16 w);
+
+#define O(o) void o ## _full(); void o ## _partial()
+
+ O(adc_ipx);
+ O(add_imm);
+ O(add_zpg);
+ O(add_zpx);
+ O(and_ipx);
+ O(asr_acc);
+ O(bar_amr);
+ O(bas_amr);
+ O(brk_r_imp);
+ O(clw_imp);
+ O(cmp_ipx);
+ O(eor_ipx);
+ O(exc_zpx);
+ O(ini_imp);
+ O(jpi_ind);
+ O(jsb_vec);
+ O(jmp_r_ind);
+ O(jsr_r_adr);
+ O(lab_acc);
+ O(lai_imp);
+ O(lan_imp);
+ O(lda_ipx);
+ O(lii_imp);
+ O(mpa_imp);
+ O(mpy_imp);
+ O(neg_acc);
+ O(nxt_imp);
+ O(ora_ipx);
+ O(phi_imp);
+ O(phw_imp);
+ O(pia_imp);
+ O(pli_imp);
+ O(plw_imp);
+ O(psh_imp);
+ O(pul_imp);
+ O(rba_ima);
+ O(rnd_imp);
+ O(rts_r_imp);
+ O(sba_ima);
+ O(sbc_ipx);
+ O(sta_ipx);
+ O(sti_imz);
+ O(taw_imp);
+ O(tip_imp);
+ O(twa_imp);
+ O(reset_r);
+
+#undef O
+
+ u16 m_w;
+ u16 m_i;
+
+ optional_shared_ptr<u8> m_page1_ram;
+ u8 m_cir;
+};
+
+class c39_device : public r65c19_device
+{
+public:
+ enum {
+ C39_BSR0 = R65C19_I + 1,
+ C39_BSR1, C39_BSR2, C39_BSR3, C39_BSR4, C39_BSR5, C39_BSR6, C39_BSR7
+ };
+
+protected:
+ c39_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map);
+
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ u8 pbs_r();
+ void pbs_w(u8 data);
+ u8 bsr_r(offs_t offset);
+ void bsr_w(offs_t offset, u8 data);
+ u8 expansion_r(offs_t offset);
+ void expansion_w(offs_t offset, u8 data);
+
+private:
+ class mi_banked : public memory_interface {
+ public:
+ virtual u8 read(u16 adr) override;
+ virtual u8 read_sync(u16 adr) override;
+ virtual u8 read_arg(u16 adr) override;
+ virtual void write(u16 adr, u8 val) override;
+
+ u8 exp_read(u16 adr);
+ u8 exp_read_cached(u16 adr);
+ void exp_write(u16 adr, u8 val);
+ u8 es4_read(u16 adr);
+ void es4_write(u16 adr, u8 val);
+
+ memory_access<21, 0, 0, ENDIANNESS_LITTLE>::cache escache;
+ memory_access<21, 0, 0, ENDIANNESS_LITTLE>::specific exp;
+ memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific es4;
+
+ u8 bsr[8];
+ u8 pbs;
+ };
+
+ address_space_config m_exp_config;
+ address_space_config m_es4_config;
+};
+
+class l2800_device : public c39_device
+{
+public:
+ l2800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+private:
+ void internal_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(R65C19, r65c19_device)
+DECLARE_DEVICE_TYPE(L2800, l2800_device)
+
+#endif // MAME_CPU_M6502_R65C19_H
diff --git a/src/devices/cpu/m6502/r65c19d.cpp b/src/devices/cpu/m6502/r65c19d.cpp
new file mode 100644
index 00000000000..6f244a79151
--- /dev/null
+++ b/src/devices/cpu/m6502/r65c19d.cpp
@@ -0,0 +1,10 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "r65c19d.h"
+#include "cpu/m6502/r65c19d.hxx"
+
+r65c19_disassembler::r65c19_disassembler() : m6502_base_disassembler(disasm_entries)
+{
+}
diff --git a/src/devices/cpu/m6502/r65c19d.h b/src/devices/cpu/m6502/r65c19d.h
new file mode 100644
index 00000000000..1b6466a0e6f
--- /dev/null
+++ b/src/devices/cpu/m6502/r65c19d.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_CPU_M6502_R65C19D_H
+#define MAME_CPU_M6502_R65C19D_H
+
+#pragma once
+
+#include "m6502d.h"
+
+class r65c19_disassembler : public m6502_base_disassembler
+{
+public:
+ r65c19_disassembler();
+ virtual ~r65c19_disassembler() = default;
+
+private:
+ static const disasm_entry disasm_entries[0x100];
+};
+
+#endif
diff --git a/src/devices/cpu/m6502/rp2a03.cpp b/src/devices/cpu/m6502/rp2a03.cpp
new file mode 100644
index 00000000000..4132e780d5a
--- /dev/null
+++ b/src/devices/cpu/m6502/rp2a03.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ rp2a03.cpp
+
+ 6502, NES variant
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rp2a03.h"
+#include "rp2a03d.h"
+
+DEFINE_DEVICE_TYPE(RP2A03_CORE, rp2a03_core_device, "rp2a03_core", "Ricoh RP2A03 core") // needed for some VT systems with XOP instead of standard APU
+DEFINE_DEVICE_TYPE(RP2A03, rp2a03_device, "rp2a03", "Ricoh RP2A03") // earliest version, found in punchout, spnchout, dkong3, VS. systems, and some early Famicoms
+DEFINE_DEVICE_TYPE(RP2A03G, rp2a03g_device, "rp2a03g", "Ricoh RP2A03G") // later revision, found in front-loader NES
+
+
+void rp2a03_device::rp2a03_map(address_map &map)
+{
+ map(0x4000, 0x4013).w(m_apu, FUNC(nesapu_device::write));
+ map(0x4015, 0x4015).lw8(NAME([this](u8 data) { m_apu->write(0x15, data); }));
+ map(0x4017, 0x4017).lw8(NAME([this](u8 data) { m_apu->write(0x17, data); }));
+ map(0x4015, 0x4015).r(m_apu, FUNC(nesapu_device::status_r));
+ // 0x4014 w -> NES sprite DMA (is this internal?)
+ // 0x4016 w -> d0-d2: RP2A03 OUT0,OUT1,OUT2
+ // 0x4016 r -> d0-d4: RP2A03 IN0
+ // 0x4017 r -> d0-d4: RP2A03 IN1
+}
+
+
+
+rp2a03_core_device::rp2a03_core_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : m6502_device(mconfig, type, tag, owner, clock)
+{
+}
+
+rp2a03_core_device::rp2a03_core_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rp2a03_core_device(mconfig, RP2A03_CORE, tag, owner, clock)
+{
+}
+
+
+
+rp2a03_device::rp2a03_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : rp2a03_core_device(mconfig, type, tag, owner, clock)
+ , device_mixer_interface(mconfig, *this)
+ , m_apu(*this, "nesapu")
+{
+ program_config.m_internal_map = address_map_constructor(FUNC(rp2a03_device::rp2a03_map), this);
+}
+
+rp2a03_device::rp2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rp2a03_device(mconfig, RP2A03, tag, owner, clock)
+{
+}
+
+rp2a03g_device::rp2a03g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rp2a03_device(mconfig, RP2A03G, tag, owner, clock)
+{
+}
+
+
+
+std::unique_ptr<util::disasm_interface> rp2a03_core_device::create_disassembler()
+{
+ return std::make_unique<rp2a03_disassembler>();
+}
+
+void rp2a03_device::apu_irq(int state)
+{
+ // games relying on the APU_IRQ don't seem to work anyway? (nes software list : timelord, mig29sf, firehawk)
+ set_input_line(RP2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+uint8_t rp2a03_device::apu_read_mem(offs_t offset)
+{
+ return mintf->program.read_byte(offset);
+}
+
+void rp2a03_device::device_add_mconfig(machine_config &config)
+{
+ APU_2A03(config, m_apu, DERIVED_CLOCK(1,1));
+ m_apu->irq().set(FUNC(rp2a03_device::apu_irq));
+ m_apu->mem_read().set(FUNC(rp2a03_device::apu_read_mem));
+ m_apu->add_route(ALL_OUTPUTS, *this, 1.0, 0);
+}
+
+void rp2a03g_device::device_add_mconfig(machine_config &config)
+{
+ NES_APU(config, m_apu, DERIVED_CLOCK(1,1));
+ m_apu->irq().set(FUNC(rp2a03g_device::apu_irq));
+ m_apu->mem_read().set(FUNC(rp2a03g_device::apu_read_mem));
+ m_apu->add_route(ALL_OUTPUTS, *this, 1.0, 0);
+}
+
+
+#include "cpu/m6502/rp2a03.hxx"
diff --git a/src/devices/cpu/m6502/rp2a03.h b/src/devices/cpu/m6502/rp2a03.h
new file mode 100644
index 00000000000..4112bbbe152
--- /dev/null
+++ b/src/devices/cpu/m6502/rp2a03.h
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ rp2a03.h
+
+ 6502, NES variant
+
+***************************************************************************/
+#ifndef MAME_CPU_M6502_RP2A03_H
+#define MAME_CPU_M6502_RP2A03_H
+
+#pragma once
+
+#include "m6502.h"
+#include "sound/nes_apu.h"
+
+class rp2a03_core_device : public m6502_device {
+public:
+ rp2a03_core_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ virtual void do_exec_full() override;
+ virtual void do_exec_partial() override;
+
+protected:
+ rp2a03_core_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+#define O(o) void o ## _full(); void o ## _partial()
+
+ // rp2a03 opcodes - same as 6502 with D disabled
+ O(adc_nd_aba); O(adc_nd_abx); O(adc_nd_aby); O(adc_nd_idx); O(adc_nd_idy); O(adc_nd_imm); O(adc_nd_zpg); O(adc_nd_zpx);
+ O(arr_nd_imm);
+ O(isb_nd_aba); O(isb_nd_abx); O(isb_nd_aby); O(isb_nd_idx); O(isb_nd_idy); O(isb_nd_zpg); O(isb_nd_zpx);
+ O(rra_nd_aba); O(rra_nd_abx); O(rra_nd_aby); O(rra_nd_idx); O(rra_nd_idy); O(rra_nd_zpg); O(rra_nd_zpx);
+ O(sbc_nd_aba); O(sbc_nd_abx); O(sbc_nd_aby); O(sbc_nd_idx); O(sbc_nd_idy); O(sbc_nd_imm); O(sbc_nd_zpg); O(sbc_nd_zpx);
+
+#undef O
+
+private:
+};
+
+class rp2a03_device : public rp2a03_core_device, public device_mixer_interface {
+public:
+ rp2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void rp2a03_map(address_map &map) ATTR_COLD;
+
+protected:
+ rp2a03_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ required_device<nesapu_device> m_apu;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void apu_irq(int state);
+ uint8_t apu_read_mem(offs_t offset);
+};
+
+class rp2a03g_device : public rp2a03_device
+{
+public:
+ rp2a03g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+/* These are the official XTAL values and clock rates used by Nintendo for
+ manufacturing throughout the production of the 2A03. PALC_APU_CLOCK is
+ the clock rate devised by UMC(?) for PAL Famicom clone hardware. */
+
+#define RP2A03_NTSC_XTAL XTAL(21'477'272)
+#define RP2A03_PAL_XTAL XTAL(26'601'712)
+#define NTSC_APU_CLOCK (RP2A03_NTSC_XTAL/12) /* 1.7897726666... MHz */
+#define PAL_APU_CLOCK (RP2A03_PAL_XTAL/16) /* 1.662607 MHz */
+#define PALC_APU_CLOCK (RP2A03_PAL_XTAL/15) /* 1.77344746666... MHz */
+
+enum {
+ RP2A03_IRQ_LINE = m6502_device::IRQ_LINE,
+ RP2A03_APU_IRQ_LINE = m6502_device::APU_IRQ_LINE,
+ RP2A03_NMI_LINE = m6502_device::NMI_LINE,
+ RP2A03_SET_OVERFLOW = m6502_device::V_LINE
+};
+
+DECLARE_DEVICE_TYPE(RP2A03_CORE, rp2a03_core_device)
+DECLARE_DEVICE_TYPE(RP2A03, rp2a03_device)
+DECLARE_DEVICE_TYPE(RP2A03G, rp2a03g_device)
+
+#endif // MAME_CPU_M6502_RP2A03_H
diff --git a/src/devices/cpu/m6502/n2a03d.cpp b/src/devices/cpu/m6502/rp2a03d.cpp
index bedb062f018..b7a34885345 100644
--- a/src/devices/cpu/m6502/n2a03d.cpp
+++ b/src/devices/cpu/m6502/rp2a03d.cpp
@@ -2,16 +2,16 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- n2a03d.cpp
+ rp2a03d.cpp
6502, NES variant, disassembler
***************************************************************************/
#include "emu.h"
-#include "n2a03d.h"
-#include "cpu/m6502/n2a03d.hxx"
+#include "rp2a03d.h"
+#include "cpu/m6502/rp2a03d.hxx"
-n2a03_disassembler::n2a03_disassembler() : m6502_base_disassembler(disasm_entries)
+rp2a03_disassembler::rp2a03_disassembler() : m6502_base_disassembler(disasm_entries)
{
}
diff --git a/src/devices/cpu/m6502/n2a03d.h b/src/devices/cpu/m6502/rp2a03d.h
index 568df91c23a..3ec3d8e4606 100644
--- a/src/devices/cpu/m6502/n2a03d.h
+++ b/src/devices/cpu/m6502/rp2a03d.h
@@ -2,24 +2,24 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- n2a03d.h
+ rp2a03d.h
6502, NES variant, disassembler
***************************************************************************/
-#ifndef MAME_CPU_M6502_N2A03D_H
-#define MAME_CPU_M6502_N2A03D_H
+#ifndef MAME_CPU_M6502_RP2A03D_H
+#define MAME_CPU_M6502_RP2A03D_H
#pragma once
#include "m6502d.h"
-class n2a03_disassembler : public m6502_base_disassembler
+class rp2a03_disassembler : public m6502_base_disassembler
{
public:
- n2a03_disassembler();
- virtual ~n2a03_disassembler() = default;
+ rp2a03_disassembler();
+ virtual ~rp2a03_disassembler() = default;
private:
static const disasm_entry disasm_entries[0x100];
diff --git a/src/devices/cpu/m6502/st2204.cpp b/src/devices/cpu/m6502/st2204.cpp
new file mode 100644
index 00000000000..cc18732226e
--- /dev/null
+++ b/src/devices/cpu/m6502/st2204.cpp
@@ -0,0 +1,728 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2202 8-Bit Integrated Microcontroller
+ Sitronix ST2204 8-Bit Integrated Microcontroller
+
+ Functional blocks:
+ * Interrupt controller (11 levels excluding BRK and RESET)
+ * GPIO (6 ports, 8 bits each)
+ * External bus (up to 7 CS outputs, 48M maximum addressable)
+ * Timers/event counters with clocking outputs (2 plus base timer)
+ * Programmable sound generator (2 channels plus DAC)
+ * LCD controller (ST2202: 240x120 B/W, software gray levels)
+ (ST2204: 320x240 B/W or 240x160 4-gray)
+ * Serial peripheral interface
+ * UART (built-in BRG; RS-232 and IrDA modes)
+ * Direct memory access (1 channel)
+ * Power down modes (WAI-0, WAI-1, STP)
+ * Watchdog timer
+ * Low voltage detector
+ * 256K (ST2202) or 512K (ST2204) ROM (may be disabled)
+ * 4K (ST2202) or 10K (ST2204) RAM
+
+ Emulation is largely based on documentation for the ST2202. The
+ ST2204 is believed to be almost entirely backward compatible.
+
+ Two versions of the ST2204 were manufactured: ST2204A, fabricated
+ by TSMC, and ST2204B, fabricated by Hyundai. A PDF document
+ describing the differences between these two was once available.
+
+ Reverse-engineered documentation for ST2204's internal registers:
+ http://blog.kevtris.org/blogfiles/Game%20King%20Inside.txt
+
+**********************************************************************/
+
+#include "emu.h"
+#include "st2204.h"
+
+DEFINE_DEVICE_TYPE(ST2202, st2202_device, "st2202", "Sitronix ST2202 Integrated Microcontroller")
+DEFINE_DEVICE_TYPE(ST2204, st2204_device, "st2204", "Sitronix ST2204 Integrated Microcontroller")
+
+st2204_device::st2204_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map)
+ : st2xxx_device(mconfig, type, tag, owner, clock, map, 26, false) // logical; only 23 address lines are brought out
+ , m_dac_callback(*this)
+ , m_tmode{0}
+ , m_tcntr{0}
+ , m_tload{0}
+ , m_timer{0}
+ , m_psg{0}
+ , m_psgc(0)
+ , m_vol(0)
+ , m_dac(0)
+ , m_psg_timer(nullptr)
+ , m_dms(0)
+ , m_dmd(0)
+ , m_dcnth(0)
+{
+}
+
+st2204_device::st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : st2204_device(mconfig, ST2204, tag, owner, clock, address_map_constructor(FUNC(st2204_device::int_map), this))
+{
+}
+
+st2202_device::st2202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : st2204_device(mconfig, ST2202, tag, owner, clock, address_map_constructor(FUNC(st2202_device::int_map), this))
+{
+}
+
+void st2204_device::device_start()
+{
+ std::unique_ptr<mi_st2204> intf = std::make_unique<mi_st2204>();
+
+ space(AS_DATA).cache(intf->dcache);
+ space(AS_DATA).specific(intf->data);
+ intf->irr_enable = false;
+ intf->irr = 0;
+ intf->prr = 0;
+ intf->drr = 0;
+ intf->dmr = 0;
+ intf->irq_service = false;
+
+ init_base_timer(0x0020);
+ init_lcd_timer(0x0040);
+
+ m_timer[0] = timer_alloc(FUNC(st2204_device::t0_interrupt), this);
+ m_timer[1] = timer_alloc(FUNC(st2204_device::t1_interrupt), this);
+ m_psg_timer = timer_alloc(FUNC(st2204_device::psg_interrupt), this);
+
+ save_item(NAME(m_tmode));
+ save_item(NAME(m_tcntr));
+ save_item(NAME(m_tload));
+ save_item(NAME(m_psg));
+ save_item(NAME(m_psgc));
+ save_item(NAME(m_vol));
+ save_item(NAME(m_dac));
+ save_item(NAME(m_dms));
+ save_item(NAME(m_dmd));
+ save_item(NAME(m_dcnth));
+ save_item(NAME(intf->dmr));
+
+ mintf = std::move(intf);
+ save_common_registers();
+ init();
+
+ state_add(ST_IRR, "IRR", downcast<mi_st2204 &>(*mintf).irr).mask(0xff);
+ state_add(ST_PRR, "PRR", downcast<mi_st2204 &>(*mintf).prr).mask(0xfff);
+ state_add(ST_DRR, "DRR", downcast<mi_st2204 &>(*mintf).drr).mask(0x7ff);
+ state_add(ST_IREQ, "IREQ", m_ireq, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ state_add(ST_IENA, "IENA", m_iena, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ for (int i = 0; i < 5; i++)
+ {
+ state_add(ST_PAOUT + i, string_format("P%cOUT", 'A' + i).c_str(), m_pdata[i]);
+ state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]);
+ if (i == 2)
+ state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]);
+ if (i == 2 || i == 3)
+ state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]);
+ }
+ state_add(ST_PLOUT, "PLOUT", m_pdata[6]);
+ state_add(ST_PCL, "PCL", m_pctrl[6]);
+ state_add(ST_PMCR, "PMCR", m_pmcr);
+ state_add(ST_PRS, "PRS", m_prs, [this](u8 data) { prs_w(data); }).mask(0x60);
+ state_add(ST_BTEN, "BTEN", m_bten, [this](u8 data) { bten_w(data); }).mask(0x1f);
+ state_add(ST_BTSR, "BTSR", m_btsr).mask(0x1f);
+ state_add(ST_T0M, "T0M", m_tmode[0]).mask(0x37);
+ state_add(ST_T0C, "T0C", m_tload[0]);
+ state_add(ST_T1M, "T1M", m_tmode[1]).mask(0x1f);
+ state_add(ST_T1C, "T1C", m_tload[1]);
+ state_add(ST_PSG0, "PSG0", m_psg[0]).mask(0xfff);
+ state_add(ST_PSG1, "PSG1", m_psg[1]).mask(0xfff);
+ state_add(ST_PSGC, "PSGC", m_psgc).mask(0x7f);
+ state_add(ST_VOL, "VOL", m_vol);
+ state_add(ST_DAC, "DAC", m_dac);
+ state_add(ST_SYS, "SYS", m_sys, [this](u8 data) { sys_w(data); });
+ state_add(ST_MISC, "MISC", m_misc).mask(st2xxx_misc_mask());
+ state_add(ST_LSSA, "LSSA", m_lssa);
+ state_add(ST_LVPW, "LVPW", m_lvpw);
+ state_add(ST_LXMAX, "LXMAX", m_lxmax);
+ state_add(ST_LYMAX, "LYMAX", m_lymax);
+ state_add(ST_LPAN, "LPAN", m_lpan).mask(st2xxx_lpan_mask());
+ state_add(ST_LCTR, "LCTR", m_lctr).mask(st2xxx_lctr_mask());
+ state_add(ST_LCKR, "LCKR", m_lckr).mask(st2xxx_lckr_mask());
+ state_add(ST_LFRA, "LFRA", m_lfra).mask(0x3f);
+ state_add(ST_LAC, "LAC", m_lac).mask(0x1f);
+ state_add(ST_LPWM, "LPWM", m_lpwm).mask(st2xxx_lpwm_mask());
+ state_add(ST_SCTR, "SCTR", m_sctr);
+ state_add(ST_SCKR, "SCKR", m_sckr).mask(0x7f);
+ state_add(ST_SSR, "SSR", m_ssr).mask(0x77);
+ state_add(ST_UCTR, "UCTR", m_uctr).mask(st2xxx_uctr_mask());
+ state_add(ST_USR, "USTR", m_usr).mask(0x7f);
+ state_add(ST_IRCTR, "IRCTR", m_irctr).mask(0xc7);
+ state_add(ST_BCTR, "BCTR", m_bctr).mask(0x87);
+ state_add(ST_BRS, "BRS", m_brs);
+ state_add(ST_BDIV, "BDIV", m_bdiv);
+ state_add(ST_DMS, "DMS", m_dms);
+ state_add(ST_DMR, "DMR", downcast<mi_st2204 &>(*mintf).dmr).mask(0x7ff);
+ state_add(ST_DMD, "DMD", m_dmd);
+}
+
+void st2204_device::device_reset()
+{
+ st2xxx_device::device_reset();
+
+ m_tmode[0] = m_tmode[1] = 0;
+ m_tcntr[0] = m_tcntr[1] = 0;
+ m_tload[0] = m_tload[1] = 0;
+ m_timer[0]->adjust(attotime::never);
+ m_timer[1]->adjust(attotime::never);
+
+ m_psg[0] = m_psg[1] = 0;
+ m_psgc = 0;
+ m_vol = 0;
+ m_dac = 0;
+ m_psg_timer->enable(false);
+ m_dac_callback(0);
+
+ downcast<mi_st2204 &>(*mintf).dmr = 0;
+ // other DMA registers are undefined
+}
+
+const char *st2204_device::st2xxx_irq_name(int i) const
+{
+ switch (i)
+ {
+ case 0: return "PC0 edge";
+ case 1: return "DAC reload";
+ case 2: return "Timer 0";
+ case 3: return "Timer 1";
+ case 4: return "PA transition";
+ case 5: return "Base timer";
+ case 6: return "LCD frame";
+ case 8: return "SPI TX empty";
+ case 9: return "SPI RX ready";
+ case 10: return "UART TX";
+ case 11: return "UART RX";
+ default: return "Reserved";
+ }
+}
+
+u8 st2204_device::mi_st2204::pread(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return data.read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff));
+}
+
+u8 st2204_device::mi_st2204::preadc(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return dcache.read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff));
+}
+
+void st2204_device::mi_st2204::pwrite(u16 adr, u8 val)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ data.write_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff), val);
+}
+
+u8 st2204_device::mi_st2204::dread(u16 adr)
+{
+ return data.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+u8 st2204_device::mi_st2204::dreadc(u16 adr)
+{
+ return dcache.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+void st2204_device::mi_st2204::dwrite(u16 adr, u8 val)
+{
+ data.write_byte(u32(drr) << 15 | (adr & 0x7fff), val);
+}
+
+u8 st2204_device::mi_st2204::read(u16 adr)
+{
+ return program.read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_sync(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_arg(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_dma(u16 adr)
+{
+ if (BIT(adr, 15))
+ return dcache.read_byte(u32(dmr) << 15 | (adr & 0x7fff));
+ else
+ return read(adr);
+}
+
+u8 st2204_device::mi_st2204::read_vector(u16 adr)
+{
+ return pread(adr);
+}
+
+void st2204_device::mi_st2204::write(u16 adr, u8 val)
+{
+ program.write_byte(adr, val);
+}
+
+unsigned st2204_device::st2xxx_bt_divider(int n) const
+{
+ // 2 Hz, 8 Hz, 64 Hz, 256 Hz, 2048 Hz
+ if (n < 5)
+ return 16384 >> ((n & 1) * 2 + (n >> 1) * 5);
+ else
+ return 0;
+}
+
+u32 st2204_device::tclk_pres_div(u8 mode) const
+{
+ assert(mode < 8);
+ if (mode == 0)
+ return 0x10000;
+ else if (mode < 4)
+ return 0x20000 >> (mode * 2);
+ else if (mode == 4)
+ return 0x100;
+ else
+ return 0x8000 >> (mode * 2);
+}
+
+TIMER_CALLBACK_MEMBER(st2204_device::t0_interrupt)
+{
+ m_ireq |= 0x004;
+ update_irq_state();
+
+ // Bit 4 allows auto-reload
+ m_tcntr[0] = BIT(m_tmode[0], 4) ? m_tload[0] : 0;
+ m_timer[0]->adjust(cycles_to_attotime((256 - m_tcntr[0]) * tclk_pres_div(m_tmode[0] & 0x07)));
+}
+
+TIMER_CALLBACK_MEMBER(st2204_device::t1_interrupt)
+{
+ m_ireq |= 0x008;
+ update_irq_state();
+
+ // Bit 4 allows auto-reload
+ m_tcntr[1] = BIT(m_tmode[1], 4) ? m_tload[1] : 0;
+ if (!BIT(m_tmode[1], 3))
+ m_timer[1]->adjust(cycles_to_attotime((256 - m_tcntr[1]) * tclk_pres_div(m_tmode[1] & 0x07)));
+ else if ((m_tmode[1] & 0x07) < 3)
+ t1_start_from_oscx();
+}
+
+void st2204_device::timer_start_from_tclk(int t)
+{
+ u32 div = tclk_pres_div(m_tmode[t] & 0x07);
+ m_timer[t]->adjust(cycles_to_attotime((255 - m_tcntr[t]) * div + div - (pres_count() & (div - 1))));
+}
+
+void st2204_device::t1_start_from_oscx()
+{
+ u32 div = 256 >> (m_tmode[1] & 0x03);
+ m_timer[1]->adjust(attotime::from_ticks(div, 32768));
+}
+
+u8 st2204_device::t0m_r()
+{
+ return m_tmode[0];
+}
+
+void st2204_device::t0m_w(u8 data)
+{
+ u8 t0m_old = std::exchange(m_tmode[0], data & 0x37);
+
+ if ((data & 0x27) != (t0m_old & 0x27) && (m_prs & 0x60) == 0x40)
+ {
+ // forced update
+ m_tcntr[0] = t0c_r();
+
+ if (BIT(data, 5))
+ timer_start_from_tclk(0);
+ else if (BIT(t0m_old, 5))
+ m_timer[0]->adjust(attotime::never);
+ }
+}
+
+u8 st2204_device::t0c_r()
+{
+ if ((m_prs & 0x60) != 0x40 || !BIT(m_tmode[0], 5))
+ return m_tcntr[0];
+ else
+ {
+ u32 div = tclk_pres_div(m_tmode[0] & 0x07);
+ return 255 - u8(attotime_to_cycles(m_timer[0]->remaining()) / div);
+ }
+}
+
+void st2204_device::t0c_w(u8 data)
+{
+ m_tcntr[0] = m_tload[0] = data;
+ if ((m_prs & 0x60) == 0x40 && BIT(m_tmode[0], 5))
+ timer_start_from_tclk(0);
+}
+
+u8 st2204_device::t1m_r()
+{
+ return m_tmode[1];
+}
+
+void st2204_device::t1m_w(u8 data)
+{
+ data &= 0x1f;
+ u8 t1m_old = std::exchange(m_tmode[1], data);
+
+ if ((data & 0x0f) != (t1m_old & 0x0f))
+ {
+ // forced update
+ m_tcntr[1] = t1c_r();
+
+ if (!BIT(data, 3))
+ {
+ if ((m_prs & 0x60) == 0x40)
+ timer_start_from_tclk(1);
+ else
+ m_timer[1]->adjust(attotime::never);
+ }
+ else if (data < 0x0b)
+ t1_start_from_oscx();
+
+ // TODO: BGRCK source
+ }
+
+}
+
+u8 st2204_device::t1c_r()
+{
+ if (!BIT(m_tmode[1], 3))
+ {
+ if ((m_prs & 0x60) != 0x40)
+ return m_tcntr[1];
+ else
+ {
+ u32 div = tclk_pres_div(m_tmode[1] & 0x07);
+ return 255 - u8(attotime_to_cycles(m_timer[1]->remaining()) / div);
+ }
+ }
+ else if ((m_tmode[1] & 0x07) < 3)
+ {
+ u32 div = 256 >> (m_tmode[1] & 0x03);
+ return 255 - u8(m_timer[1]->remaining().as_ticks(32768) / div);
+ }
+ else
+ return m_tcntr[1];
+}
+
+void st2204_device::t1c_w(u8 data)
+{
+ m_tcntr[1] = m_tload[1] = data;
+}
+
+void st2204_device::st2xxx_tclk_start()
+{
+ if (BIT(m_tmode[0], 5))
+ timer_start_from_tclk(0);
+ if (!BIT(m_tmode[1], 3))
+ timer_start_from_tclk(1);
+}
+
+void st2204_device::st2xxx_tclk_stop()
+{
+ if (m_timer[0]->enabled())
+ {
+ m_tcntr[0] = t0c_r();
+ m_timer[0]->adjust(attotime::never);
+ }
+ if (!BIT(m_tmode[1], 3))
+ {
+ m_tcntr[1] = t1c_r();
+ m_timer[1]->adjust(attotime::never);
+ }
+}
+
+TIMER_CALLBACK_MEMBER(st2204_device::psg_interrupt)
+{
+ m_ireq |= 0x002;
+ update_irq_state();
+
+ psg_timer_reload();
+}
+
+void st2204_device::psg_timer_reload()
+{
+ unsigned count;
+ if (BIT(m_psgc, 0))
+ count = (0x40 - BIT(m_psg[1], 6, 6)) * (0x40 - BIT(m_psg[1], 0, 6)) * 64;
+ else if ((m_psgc & 0x0d) == 0x04)
+ count = 0x1000 - m_psg[1];
+ else
+ return;
+
+ if ((m_psgc & 0x70) == 0x40)
+ m_psg_timer->adjust(cycles_to_attotime(count));
+ else if ((m_psgc & 0x70) == 0x70)
+ m_psg_timer->adjust(attotime::from_ticks(count, 32768));
+ else
+ m_psg_timer->adjust(cycles_to_attotime(count << (BIT(m_psgc, 4, 2) + 1)));
+}
+
+u8 st2204_device::psg_r(offs_t offset)
+{
+ // TODO: instantaneous upcount value
+ if (BIT(offset, 0))
+ return (m_psg[offset >> 1] >> 8) | 0xf0;
+ else
+ return m_psg[offset >> 1] & 0x0ff;
+}
+
+void st2204_device::psg_w(offs_t offset, u8 data)
+{
+ if (BIT(offset, 0))
+ m_psg[offset >> 1] = u16(data & 0x0f) << 8 | (m_psg[offset >> 1] & 0x0ff);
+ else
+ m_psg[offset >> 1] = data | (m_psg[offset >> 1] & 0xf00);
+}
+
+u8 st2204_device::psgc_r()
+{
+ return m_psgc | 0x80;
+}
+
+void st2204_device::psgc_w(u8 data)
+{
+ m_psgc = data & 0x7f;
+
+ if (!m_psg_timer->enabled())
+ psg_timer_reload();
+}
+
+u8 st2204_device::vol_r()
+{
+ return m_vol;
+}
+
+void st2204_device::vol_w(u8 data)
+{
+ m_vol = data;
+}
+
+u8 st2204_device::dac_r()
+{
+ return m_dac;
+}
+
+void st2204_device::dac_w(u8 data)
+{
+ // TODO: emulate PSG/PWM more accurately within device
+ m_dac_callback(data);
+ m_dac = data;
+}
+
+unsigned st2204_device::st2xxx_lfr_clocks() const
+{
+ // ST2202 datasheet suggests 1/4 as many clocks in 4-bit mode; this seems too fast for GameKing 3 (TODO: double-check this)
+ unsigned lcdcks = ((m_lxmax + m_lfra) * 2 + 3) * 8 * (m_lymax ? m_lymax : 256);
+
+ if (BIT(m_lckr, 4))
+ return lcdcks * std::max((m_lckr & 0x0f) * 2, 1);
+ else
+ return lcdcks * std::max(((m_lckr & 0x0c) >> 2) * 2, 1);
+}
+
+u8 st2204_device::dmsl_r()
+{
+ return m_dms & 0xff;
+}
+
+void st2204_device::dmsl_w(u8 data)
+{
+ m_dms = (m_dms & 0xff00) | data;
+}
+
+u8 st2204_device::dmsh_r()
+{
+ return m_dms >> 8;
+}
+
+void st2204_device::dmsh_w(u8 data)
+{
+ m_dms = (m_dms & 0x00ff) | u16(data) << 8;
+}
+
+u8 st2204_device::dmdl_r()
+{
+ return m_dmd & 0xff;
+}
+
+void st2204_device::dmdl_w(u8 data)
+{
+ m_dmd = (m_dmd & 0xff00) | data;
+}
+
+u8 st2204_device::dmdh_r()
+{
+ return m_dmd >> 8;
+}
+
+void st2204_device::dmdh_w(u8 data)
+{
+ m_dmd = (m_dmd & 0x00ff) | u16(data) << 8;
+}
+
+void st2204_device::dcntl_w(u8 data)
+{
+ u16 count = data | u16(m_dcnth & 0x0f) << 8;
+
+ // FIXME: not instantaneous (obviously), but takes 2 cycles per transfer while CPU is halted
+ mi_st2204 &intf = downcast<mi_st2204 &>(*mintf);
+ while (count != 0xffff)
+ {
+ intf.write(m_dmd, intf.read_dma(m_dms));
+
+ if (m_dms++ == 0xffff)
+ {
+ // DMR bank increments automatically when source is in data memory
+ m_dms = 0x8000;
+ intf.dmr = (intf.dmr + 1) & 0x7ff;
+ }
+
+ // DMAM inhibits destination increment
+ if (!BIT(m_dcnth, 4))
+ m_dmd++;
+
+ count--;
+ }
+}
+
+void st2204_device::dcnth_w(u8 data)
+{
+ m_dcnth = data & 0x1f;
+}
+
+u8 st2204_device::dmrl_r()
+{
+ return downcast<mi_st2204 &>(*mintf).dmr & 0xff;
+}
+
+void st2204_device::dmrl_w(u8 data)
+{
+ u16 &dmr = downcast<mi_st2204 &>(*mintf).dmr;
+ dmr = (data & m_drr_mask) | (dmr & 0xff00);
+}
+
+u8 st2204_device::dmrh_r()
+{
+ return downcast<mi_st2204 &>(*mintf).dmr >> 8;
+}
+
+void st2204_device::dmrh_w(u8 data)
+{
+ u16 &dmr = downcast<mi_st2204 &>(*mintf).dmr;
+ dmr = ((u16(data) << 8) & m_drr_mask) | (dmr & 0x00ff);
+}
+
+u8 st2204_device::pmem_r(offs_t offset)
+{
+ return downcast<mi_st2204 &>(*mintf).pread(offset);
+}
+
+void st2204_device::pmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2204 &>(*mintf).pwrite(offset, data);
+}
+
+u8 st2204_device::dmem_r(offs_t offset)
+{
+ return downcast<mi_st2204 &>(*mintf).dread(offset);
+}
+
+void st2204_device::dmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2204 &>(*mintf).dwrite(offset, data);
+}
+
+void st2204_device::common_map(address_map &map)
+{
+ map(0x0000, 0x0004).rw(FUNC(st2204_device::pdata_r), FUNC(st2204_device::pdata_w));
+ map(0x0005, 0x0005).rw(FUNC(st2204_device::psc_r), FUNC(st2204_device::psc_w));
+ map(0x0008, 0x000c).rw(FUNC(st2204_device::pctrl_r), FUNC(st2204_device::pctrl_w));
+ map(0x000d, 0x000d).rw(FUNC(st2204_device::pfc_r), FUNC(st2204_device::pfc_w));
+ map(0x000e, 0x000e).rw(FUNC(st2204_device::pfd_r), FUNC(st2204_device::pfd_w));
+ map(0x000f, 0x000f).rw(FUNC(st2204_device::pmcr_r), FUNC(st2204_device::pmcr_w));
+ map(0x0010, 0x0013).w(FUNC(st2204_device::psg_w));
+ map(0x0014, 0x0014).w(FUNC(st2204_device::dac_w));
+ map(0x0016, 0x0016).w(FUNC(st2204_device::psgc_w));
+ map(0x0017, 0x0017).w(FUNC(st2204_device::vol_w));
+ map(0x0020, 0x0020).rw(FUNC(st2204_device::bten_r), FUNC(st2204_device::bten_w));
+ map(0x0021, 0x0021).rw(FUNC(st2204_device::btsr_r), FUNC(st2204_device::btclr_all_w));
+ map(0x0023, 0x0023).rw(FUNC(st2204_device::prs_r), FUNC(st2204_device::prs_w));
+ map(0x0024, 0x0024).rw(FUNC(st2204_device::t0m_r), FUNC(st2204_device::t0m_w));
+ map(0x0025, 0x0025).rw(FUNC(st2204_device::t0c_r), FUNC(st2204_device::t0c_w));
+ map(0x0026, 0x0026).rw(FUNC(st2204_device::t1m_r), FUNC(st2204_device::t1m_w));
+ map(0x0027, 0x0027).rw(FUNC(st2204_device::t1c_r), FUNC(st2204_device::t1c_w));
+ map(0x0028, 0x0028).w(FUNC(st2204_device::dmsl_w));
+ map(0x0029, 0x0029).w(FUNC(st2204_device::dmsh_w));
+ map(0x002a, 0x002a).w(FUNC(st2204_device::dmdl_w));
+ map(0x002b, 0x002b).w(FUNC(st2204_device::dmdh_w));
+ map(0x002c, 0x002c).w(FUNC(st2204_device::dcntl_w));
+ map(0x002d, 0x002d).w(FUNC(st2204_device::dcnth_w));
+ map(0x0030, 0x0030).rw(FUNC(st2204_device::sys_r), FUNC(st2204_device::sys_w));
+ map(0x0031, 0x0031).rw(FUNC(st2204_device::irrl_r), FUNC(st2204_device::irrl_w));
+ map(0x0032, 0x0032).rw(FUNC(st2204_device::prrl_r), FUNC(st2204_device::prrl_w));
+ map(0x0033, 0x0033).rw(FUNC(st2204_device::prrh_r), FUNC(st2204_device::prrh_w));
+ map(0x0034, 0x0034).rw(FUNC(st2204_device::drrl_r), FUNC(st2204_device::drrl_w));
+ map(0x0035, 0x0035).rw(FUNC(st2204_device::drrh_r), FUNC(st2204_device::drrh_w));
+ map(0x0036, 0x0036).rw(FUNC(st2204_device::dmrl_r), FUNC(st2204_device::dmrl_w));
+ map(0x0037, 0x0037).rw(FUNC(st2204_device::dmrh_r), FUNC(st2204_device::dmrh_w));
+ map(0x0038, 0x0038).rw(FUNC(st2204_device::misc_r), FUNC(st2204_device::misc_w));
+ map(0x003c, 0x003c).rw(FUNC(st2204_device::ireql_r), FUNC(st2204_device::ireql_w));
+ map(0x003d, 0x003d).rw(FUNC(st2204_device::ireqh_r), FUNC(st2204_device::ireqh_w));
+ map(0x003e, 0x003e).rw(FUNC(st2204_device::ienal_r), FUNC(st2204_device::ienal_w));
+ map(0x003f, 0x003f).rw(FUNC(st2204_device::ienah_r), FUNC(st2204_device::ienah_w));
+ map(0x0040, 0x0040).w(FUNC(st2204_device::lssal_w));
+ map(0x0041, 0x0041).w(FUNC(st2204_device::lssah_w));
+ map(0x0042, 0x0042).w(FUNC(st2204_device::lvpw_w));
+ map(0x0043, 0x0043).rw(FUNC(st2204_device::lxmax_r), FUNC(st2204_device::lxmax_w));
+ map(0x0044, 0x0044).rw(FUNC(st2204_device::lymax_r), FUNC(st2204_device::lymax_w));
+ map(0x0045, 0x0045).rw(FUNC(st2204_device::lpan_r), FUNC(st2204_device::lpan_w));
+ map(0x0047, 0x0047).rw(FUNC(st2204_device::lctr_r), FUNC(st2204_device::lctr_w));
+ map(0x0048, 0x0048).w(FUNC(st2204_device::lckr_w));
+ map(0x0049, 0x0049).w(FUNC(st2204_device::lfra_w));
+ map(0x004a, 0x004a).rw(FUNC(st2204_device::lac_r), FUNC(st2204_device::lac_w));
+ map(0x004b, 0x004b).rw(FUNC(st2204_device::lpwm_r), FUNC(st2204_device::lpwm_w));
+ map(0x004c, 0x004c).rw(FUNC(st2204_device::pl_r), FUNC(st2204_device::pl_w));
+ // PCL is listed as write-only in ST2202 specification, but DynamiDesk suggests otherwise
+ map(0x004e, 0x004e).rw(FUNC(st2204_device::pcl_r), FUNC(st2204_device::pcl_w));
+ map(0x0052, 0x0052).rw(FUNC(st2204_device::sctr_r), FUNC(st2204_device::sctr_w));
+ map(0x0053, 0x0053).rw(FUNC(st2204_device::sckr_r), FUNC(st2204_device::sckr_w));
+ map(0x0054, 0x0054).rw(FUNC(st2204_device::ssr_r), FUNC(st2204_device::ssr_w));
+ map(0x0060, 0x0060).rw(FUNC(st2204_device::uctr_r), FUNC(st2204_device::uctr_w));
+ map(0x0061, 0x0061).rw(FUNC(st2204_device::usr_r), FUNC(st2204_device::ustr_trg_w));
+ map(0x0062, 0x0062).rw(FUNC(st2204_device::irctr_r), FUNC(st2204_device::irctr_w));
+ map(0x0063, 0x0063).rw(FUNC(st2204_device::bctr_r), FUNC(st2204_device::bctr_w));
+ map(0x0066, 0x0066).rw(FUNC(st2204_device::brs_r), FUNC(st2204_device::brs_w));
+ map(0x0067, 0x0067).rw(FUNC(st2204_device::bdiv_r), FUNC(st2204_device::bdiv_w));
+ map(0x4000, 0x7fff).rw(FUNC(st2204_device::pmem_r), FUNC(st2204_device::pmem_w));
+ map(0x8000, 0xffff).rw(FUNC(st2204_device::dmem_r), FUNC(st2204_device::dmem_w));
+}
+
+void st2202_device::int_map(address_map &map)
+{
+ common_map(map);
+ map(0x0080, 0x0fff).ram();
+}
+
+void st2204_device::int_map(address_map &map)
+{
+ common_map(map);
+ // PSG registers may or may not be readable on ST2202, but are readable here
+ map(0x0010, 0x0013).r(FUNC(st2204_device::psg_r));
+ map(0x0014, 0x0014).r(FUNC(st2204_device::dac_r));
+ map(0x0016, 0x0016).r(FUNC(st2204_device::psgc_r));
+ map(0x0017, 0x0017).r(FUNC(st2204_device::vol_r));
+ // Source/destination registers are supposedly not readable on ST2202, but may be readable here (count register isn't)
+ map(0x0028, 0x0028).r(FUNC(st2204_device::dmsl_r));
+ map(0x0029, 0x0029).r(FUNC(st2204_device::dmsh_r));
+ map(0x002a, 0x002a).r(FUNC(st2204_device::dmdl_r));
+ map(0x002b, 0x002b).r(FUNC(st2204_device::dmdh_r));
+ map(0x0080, 0x287f).ram(); // 2800-287F possibly not present in earlier versions
+}
diff --git a/src/devices/cpu/m6502/st2204.h b/src/devices/cpu/m6502/st2204.h
new file mode 100644
index 00000000000..ba4ed6e9ee4
--- /dev/null
+++ b/src/devices/cpu/m6502/st2204.h
@@ -0,0 +1,163 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2202 8-Bit Integrated Microcontroller
+ Sitronix ST2204 8-Bit Integrated Microcontroller
+
+**********************************************************************/
+
+#ifndef MAME_CPU_M6502_ST2204_H
+#define MAME_CPU_M6502_ST2204_H
+
+#pragma once
+
+#include "st2xxx.h"
+
+class st2204_device : public st2xxx_device
+{
+public:
+ enum {
+ ST_T0M = ST_BDIV + 1,
+ ST_T0C,
+ ST_T1M,
+ ST_T1C,
+ ST_PSG0,
+ ST_PSG1,
+ ST_VOL,
+ ST_DAC,
+ ST_DMS,
+ ST_DMD
+ };
+
+ st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ auto dac_callback() { return m_dac_callback.bind(); }
+
+protected:
+ st2204_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor int_map);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u16 st2xxx_ireq_mask() const override { return 0x0f7f; }
+ virtual const char *st2xxx_irq_name(int i) const override;
+ virtual u8 st2xxx_pmcr_mask() const override { return 0xff; }
+ virtual unsigned st2xxx_bt_divider(int n) const override;
+ virtual u8 st2xxx_prs_mask() const override { return 0xe0; }
+ virtual void st2xxx_tclk_start() override;
+ virtual void st2xxx_tclk_stop() override;
+ virtual u8 st2xxx_sys_mask() const override { return 0xff; }
+ virtual u8 st2xxx_misc_mask() const override { return 0x1f; }
+ virtual bool st2xxx_has_dma() const override { return true; }
+ virtual u8 st2xxx_lpan_mask() const override { return 0x07; }
+ virtual u8 st2xxx_lctr_mask() const override { return 0xff; }
+ virtual u8 st2xxx_lckr_mask() const override { return 0x1f; }
+ virtual u8 st2xxx_lpwm_mask() const override { return 0x3f; }
+ virtual unsigned st2xxx_lfr_clocks() const override;
+ virtual bool st2xxx_has_spi() const override { return true; }
+ virtual u8 st2xxx_uctr_mask() const override { return 0x0f; }
+ virtual u8 st2xxx_bctr_mask() const override { return 0x87; }
+
+ void common_map(address_map &map) ATTR_COLD;
+
+private:
+ class mi_st2204 : public mi_st2xxx {
+ public:
+ virtual u8 read(u16 adr) override;
+ virtual u8 read_sync(u16 adr) override;
+ virtual u8 read_arg(u16 adr) override;
+ u8 read_dma(u16 adr);
+ virtual u8 read_vector(u16 adr) override;
+ virtual void write(u16 adr, u8 val) override;
+
+ u8 pread(u16 adr);
+ u8 preadc(u16 adr);
+ void pwrite(u16 adr, u8 val);
+ u8 dread(u16 adr);
+ u8 dreadc(u16 adr);
+ void dwrite(u16 adr, u8 val);
+
+ u16 dmr;
+ };
+
+ u32 tclk_pres_div(u8 mode) const;
+ TIMER_CALLBACK_MEMBER(t0_interrupt);
+ TIMER_CALLBACK_MEMBER(t1_interrupt);
+ void timer_start_from_tclk(int t);
+ void t1_start_from_oscx();
+ u8 t0m_r();
+ void t0m_w(u8 data);
+ u8 t0c_r();
+ void t0c_w(u8 data);
+ u8 t1m_r();
+ void t1m_w(u8 data);
+ u8 t1c_r();
+ void t1c_w(u8 data);
+
+ TIMER_CALLBACK_MEMBER(psg_interrupt);
+ void psg_timer_reload();
+ u8 psg_r(offs_t offset);
+ void psg_w(offs_t offset, u8 data);
+ u8 psgc_r();
+ void psgc_w(u8 data);
+ u8 vol_r();
+ void vol_w(u8 data);
+ u8 dac_r();
+ void dac_w(u8 data);
+
+ u8 dmsl_r();
+ void dmsl_w(u8 data);
+ u8 dmsh_r();
+ void dmsh_w(u8 data);
+ u8 dmdl_r();
+ void dmdl_w(u8 data);
+ u8 dmdh_r();
+ void dmdh_w(u8 data);
+ void dcntl_w(u8 data);
+ void dcnth_w(u8 data);
+ u8 dmrl_r();
+ void dmrl_w(u8 data);
+ u8 dmrh_r();
+ void dmrh_w(u8 data);
+
+ u8 pmem_r(offs_t offset);
+ void pmem_w(offs_t offset, u8 data);
+ u8 dmem_r(offs_t offset);
+ void dmem_w(offs_t offset, u8 data);
+
+ void int_map(address_map &map) ATTR_COLD;
+
+ devcb_write8 m_dac_callback;
+
+ u8 m_tmode[2];
+ u8 m_tcntr[2];
+ u8 m_tload[2];
+ emu_timer *m_timer[2];
+ u16 m_psg[2];
+ u8 m_psgc;
+ u8 m_vol;
+ u8 m_dac;
+ emu_timer *m_psg_timer;
+ u16 m_dms;
+ u16 m_dmd;
+ u8 m_dcnth;
+};
+
+class st2202_device : public st2204_device
+{
+public:
+ st2202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual u8 st2xxx_misc_mask() const override { return 0x0f; }
+ virtual u8 st2xxx_lctr_mask() const override { return 0xe0; }
+
+private:
+ void int_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(ST2202, st2202_device)
+DECLARE_DEVICE_TYPE(ST2204, st2204_device)
+
+#endif // MAME_MACHINE_M6502_ST2204_H
diff --git a/src/devices/cpu/m6502/st2205u.cpp b/src/devices/cpu/m6502/st2205u.cpp
new file mode 100644
index 00000000000..cf7639b9aca
--- /dev/null
+++ b/src/devices/cpu/m6502/st2205u.cpp
@@ -0,0 +1,1354 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2205U 8-Bit Integrated Microcontroller
+
+ Functional blocks:
+ * Interrupt controller (15 levels excluding BRK and RESET)
+ * GPIO (7 ports, 8 bits each)
+ * External bus (up to 7 CS outputs, 48M maximum addressable)
+ * Timers/event counters with clocking outputs (4 plus base timer)
+ * Programmable sound generator (4 channels with FIFOs, plus PWM
+ or ADPCM DAC and 16x8 signed multiplicator)
+ * LCD controller (640x400 B/W, 400x320 4-gray, 160xRGBx120 16-gray)
+ * Serial peripheral interface
+ * UART (built-in BRG; RS-232 and IrDA modes)
+ * USB 2.0 (separate control and bulk transfer endpoint buffers)
+ * Direct memory access (2 channels, optional XOR/OR/AND logic)
+ * NAND/AND Flash memory interface (includes ECC generator)
+ * Power down modes (WAI-0, WAI-1, STP)
+ * Watchdog timer
+ * Real time clock (seconds, minutes, hours with alarm interrupts)
+ * Low voltage detector with reset
+ * 16K OTP ROM (may be disabled)
+ * 32K SRAM
+
+ One important difference between the ST2205U and almost every
+ other ST2XXX MCU is that PRR[0] and IRR[0] are *not* inverted
+ relative to A14.
+
+ ST2302U lacks the LCDC, UART and NAND interface and includes only
+ 8K mask ROM, 2K SRAM and 20 GPIO pins, but appears to be broadly
+ similar in other aspects. (The differences, if any, between
+ ST2302U and ST2312U are unclear, but ST2301U and ST2331U omit the
+ PSG.) It also supports a SYSCLK of up to 24 MHz.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "st2205u.h"
+
+#define LOG_DAC (1U << 1)
+#define LOG_DMA (1U << 2)
+//#define VERBOSE (LOG_DMA)
+#include "logmacro.h"
+
+#define LOGDAC(...) LOGMASKED(LOG_DAC, __VA_ARGS__)
+#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(ST2205U, st2205u_device, "st2205u", "Sitronix ST2205U Integrated Microcontroller")
+DEFINE_DEVICE_TYPE(ST2302U, st2302u_device, "st2302u", "Sitronix ST2302U Integrated Microcontroller")
+
+st2205u_base_device::st2205u_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram)
+ : st2xxx_device(mconfig, type, tag, owner, clock, internal_map, data_bits, has_banked_ram)
+ , device_sound_interface(mconfig, *this)
+ , m_stream(nullptr)
+ , m_btc(0)
+ , m_tc_12bit{0}
+ , m_count_12bit{0}
+ , m_timer_12bit{nullptr}
+ , m_t4c(0)
+ , m_tien(0)
+ , m_dac_fifo{{0}}
+ , m_fifo_filled{0}
+ , m_fifo_pos{0}
+ , m_psgc(0)
+ , m_psgm(0)
+ , m_psg_on(0)
+ , m_psg_vol{0}
+ , m_psg_volm{0}
+ , m_mul(0)
+ , m_usbcon(0)
+ , m_usbien(0)
+ , m_dptr{0}
+ , m_dbkr{0}
+ , m_dcnt{0}
+ , m_dctr(0)
+ , m_dmod{0}
+ , m_rctr(0)
+ , m_lvctr(0)
+{
+}
+
+st2205u_device::st2205u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : st2205u_base_device(mconfig, ST2205U, tag, owner, clock,
+ address_map_constructor(FUNC(st2205u_device::int_map), this),
+ 26, // logical; only 23 address lines are brought out
+ true)
+ , m_lbuf(0)
+ , m_lpal_index(0)
+ , m_gray_levels{0}
+{
+}
+
+st2302u_device::st2302u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : st2205u_base_device(mconfig, ST2302U, tag, owner, clock,
+ address_map_constructor(FUNC(st2302u_device::int_map), this),
+ 26, // ???
+ false)
+{
+}
+
+void st2205u_base_device::sound_stream_update(sound_stream &stream)
+{
+ int samples = stream.samples();
+ int outpos = 0;
+ while (samples-- != 0)
+ {
+ for (int channel = 0; channel < 4; channel++)
+ {
+ s16 adpcm_contribution = m_adpcm_level[channel];
+ stream.add_int(channel, outpos, adpcm_contribution * 0x10, 32768);
+
+ auto psg_contribution = std::sin((double)m_psg_freqcntr[channel]/4096.0f);
+ stream.add_int(channel, outpos, psg_contribution * m_psg_amplitude[channel]*0x80,32768);
+ }
+
+ outpos++;
+ }
+}
+
+void st2205u_base_device::base_init(std::unique_ptr<mi_st2xxx> &&intf)
+{
+ m_stream = stream_alloc(0, 4, 48000);
+
+ m_timer_12bit[0] = timer_alloc(FUNC(st2205u_device::t0_interrupt), this);
+ m_timer_12bit[1] = timer_alloc(FUNC(st2205u_device::t1_interrupt), this);
+ m_timer_12bit[2] = timer_alloc(FUNC(st2205u_device::t2_interrupt), this);
+ m_timer_12bit[3] = timer_alloc(FUNC(st2205u_device::t3_interrupt), this);
+
+ init_base_timer(0x0040);
+ init_lcd_timer(0x0080);
+
+ save_item(NAME(m_btc));
+ save_item(NAME(m_tc_12bit));
+ save_item(NAME(m_count_12bit));
+ save_item(NAME(m_t4c));
+ save_item(NAME(m_tien));
+ save_item(NAME(m_dac_fifo));
+ save_item(NAME(m_fifo_filled));
+ save_item(NAME(m_fifo_pos));
+ save_item(NAME(m_psgc));
+ save_item(NAME(m_psgm));
+ save_item(NAME(m_psg_on));
+ save_item(NAME(m_psg_vol));
+ save_item(NAME(m_psg_volm));
+ save_item(NAME(m_mul));
+ save_item(NAME(m_usbcon));
+ save_item(NAME(m_usbien));
+ save_item(NAME(m_dptr));
+ save_item(NAME(m_dbkr));
+ save_item(NAME(m_dcnt));
+ save_item(NAME(m_dctr));
+ save_item(NAME(m_dmod));
+ save_item(NAME(m_rctr));
+ save_item(NAME(m_lvctr));
+
+ save_item(NAME(m_adpcm_level));
+ save_item(NAME(m_psg_amplitude));
+ save_item(NAME(m_psg_freqcntr));
+
+ mintf = std::move(intf);
+ save_common_registers();
+ init();
+}
+
+void st2205u_device::device_start()
+{
+ std::unique_ptr<mi_st2205u> intf = std::make_unique<mi_st2205u>();
+ space(AS_DATA).specific(intf->data);
+ space(AS_DATA).cache(intf->dcache);
+ intf->irr_enable = false;
+ intf->irr = 0;
+ intf->prr = 0;
+ intf->drr = 0;
+ intf->brr = 0;
+ intf->irq_service = false;
+ intf->ram = make_unique_clear<u8[]>(0x8000);
+
+ save_item(NAME(m_lbuf));
+ save_item(NAME(m_lpal_index));
+ save_item(NAME(m_gray_levels));
+ save_item(NAME(intf->brr));
+ save_pointer(NAME(intf->ram), 0x8000);
+
+ base_init(std::move(intf));
+
+ state_add(ST_IRR, "IRR", downcast<mi_st2205u &>(*mintf).irr).mask(0x8fff);
+ state_add(ST_PRR, "PRR", downcast<mi_st2205u &>(*mintf).prr).mask(0x8fff);
+ state_add(ST_DRR, "DRR", downcast<mi_st2205u &>(*mintf).drr).mask(0x87ff);
+ state_add(ST_BRR, "BRR", downcast<mi_st2205u &>(*mintf).brr).mask(0x9fff);
+ state_add(ST_IREQ, "IREQ", m_ireq, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ state_add(ST_IENA, "IENA", m_iena, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ for (int i = 0; i < 6; i++)
+ {
+ state_add(ST_PAOUT + i, string_format("P%cOUT", 'A' + i).c_str(), m_pdata[i]);
+ state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]);
+ if (i == 2 || i == 4)
+ state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]);
+ if (i == 2 || i == 3)
+ state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]).mask(i == 2 ? 0xfe : 0xff);
+ }
+ state_add(ST_PLOUT, "PLOUT", m_pdata[6]);
+ state_add(ST_PCL, "PCL", m_pctrl[6]);
+ state_add(ST_PMCR, "PMCR", m_pmcr);
+ state_add(ST_MISC, "MISC", m_misc).mask(st2xxx_misc_mask());
+ state_add(ST_SYS, "SYS", m_sys, [this](u8 data) { sys_w(data); }).mask(0xfe);
+ state_add(ST_PRS, "PRS", m_prs, [this](u8 data) { prs_w(data); }).mask(0x40);
+ state_add(ST_BTEN, "BTEN", m_bten, [this](u8 data) { bten_w(data); });
+ state_add(ST_BTSR, "BTREQ", m_btsr);
+ state_add(ST_BTC, "BTC", m_btc);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_T0C + i, string_format("T%dC", i).c_str(), m_tc_12bit[i]);
+ state_add(ST_T4C, "T4C", m_t4c);
+ state_add(ST_TIEN, "TIEN", m_tien);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_FIFOS0 + i, string_format("FIFOS%d", i).c_str(), m_fifo_filled[i]).mask(0x1f);
+ state_add(ST_PSGC, "PSGC", m_psgc);
+ state_add(ST_PSGM, "PSGM", m_psgm);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_VOL0 + i, string_format("VOL%d", i).c_str(), m_psg_vol[i]).mask(0xbf);
+ state_add(ST_VOLM0, "VOLM0", m_psg_volm[0]).mask(0x3f);
+ state_add(ST_VOLM1, "VOLM1", m_psg_volm[1]).mask(0x7f);
+ state_add(ST_MUL, "MUL", m_mul);
+ state_add(ST_LSSA, "LSSA", m_lssa);
+ state_add(ST_LVPW, "LVPW", m_lvpw);
+ state_add(ST_LXMAX, "LXMAX", m_lxmax);
+ state_add(ST_LYMAX, "LYMAX", m_lymax);
+ state_add(ST_LPAN, "LPAN", m_lpan).mask(st2xxx_lpan_mask());
+ state_add(ST_LBUF, "LBUF", m_lbuf);
+ state_add(ST_LCTR, "LCTR", m_lctr).mask(st2xxx_lctr_mask());
+ state_add(ST_LCKR, "LCKR", m_lckr).mask(st2xxx_lckr_mask());
+ state_add(ST_LFRA, "LFRA", m_lfra).mask(0x3f);
+ state_add(ST_LAC, "LAC", m_lac).mask(0x1f);
+ state_add(ST_LPWM, "LPWM", m_lpwm).mask(st2xxx_lpwm_mask());
+ state_add(ST_SCTR, "SCTR", m_sctr);
+ state_add(ST_SCKR, "SCKR", m_sckr).mask(0x7f);
+ state_add(ST_SSR, "SSR", m_ssr).mask(0x77);
+ state_add(ST_SMOD, "SMOD", m_smod).mask(0x0f);
+ state_add(ST_UCTR, "UCTR", m_uctr).mask(st2xxx_uctr_mask());
+ state_add(ST_USR, "USR", m_usr).mask(0x7f);
+ state_add(ST_IRCTR, "IRCTR", m_irctr).mask(0xc7);
+ state_add(ST_BCTR, "BCTR", m_bctr).mask(0xb7);
+ state_add(ST_BRS, "BRS", m_brs);
+ state_add(ST_BDIV, "BDIV", m_bdiv);
+ state_add(ST_USBCON, "USBCON", m_usbcon).mask(0xfc);
+ state_add(ST_USBIEN, "USBIEN", m_usbien).mask(0xbf);
+ for (int i = 0; i < 2; i++)
+ {
+ state_add(ST_DMS0 + i, string_format("DMS%d", i).c_str(), m_dptr[i * 2]).mask(0x7fff);
+ state_add(ST_DMD0 + i, string_format("DMD%d", i).c_str(), m_dptr[i * 2 + 1]).mask(0x7fff);
+ state_add(ST_DBKS0 + i, string_format("DBKS%d", i).c_str(), m_dbkr[i * 2]).mask(0x87ff);
+ state_add(ST_DBKD0 + i, string_format("DBKD%d", i).c_str(), m_dbkr[i * 2 + 1]).mask(0x87ff);
+ state_add(ST_DCNT0 + i, string_format("DCNT%d", i).c_str(), m_dcnt[i]).mask(0x7fff);
+ state_add(ST_DMOD0 + i, string_format("DMOD%d", i).c_str(), m_dmod[i]).mask(0x3f);
+ }
+ state_add(ST_DCTR, "DCTR", m_dctr).mask(0x03);
+ state_add(ST_RCTR, "RCTR", m_rctr).mask(0xef);
+ state_add(ST_LVCTR, "LVCTR", m_lvctr).mask(0x0f);
+}
+
+void st2302u_device::device_start()
+{
+ std::unique_ptr<mi_st2302u> intf = std::make_unique<mi_st2302u>();
+ space(AS_DATA).specific(intf->data);
+ space(AS_DATA).cache(intf->dcache);
+ intf->irr_enable = false;
+ intf->irr = 0;
+ intf->prr = 0;
+ intf->drr = 0;
+ intf->irq_service = false;
+
+ base_init(std::move(intf));
+
+ state_add(ST_IRR, "IRR", downcast<mi_st2302u &>(*mintf).irr).mask(0x0fff);
+ state_add(ST_PRR, "PRR", downcast<mi_st2302u &>(*mintf).prr).mask(0x0fff);
+ state_add(ST_DRR, "DRR", downcast<mi_st2302u &>(*mintf).drr).mask(0x07ff);
+ state_add(ST_IREQ, "IREQ", m_ireq, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ state_add(ST_IENA, "IENA", m_iena, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
+ for (int i = 0; i < 6; i++)
+ {
+ state_add(ST_PAOUT + i, string_format("P%cOUT", 'A' + i).c_str(), m_pdata[i]);
+ state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]);
+ if (i == 2 || i == 4)
+ state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]);
+ if (i == 2 || i == 3)
+ state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]).mask(i == 2 ? 0xfe : 0xff);
+ }
+ state_add(ST_PMCR, "PMCR", m_pmcr);
+ state_add(ST_MISC, "MISC", m_misc).mask(st2xxx_misc_mask());
+ state_add(ST_SYS, "SYS", m_sys, [this](u8 data) { sys_w(data); }).mask(0xfe);
+ state_add(ST_PRS, "PRS", m_prs, [this](u8 data) { prs_w(data); }).mask(0x40);
+ state_add(ST_BTEN, "BTEN", m_bten, [this](u8 data) { bten_w(data); });
+ state_add(ST_BTSR, "BTREQ", m_btsr);
+ state_add(ST_BTC, "BTC", m_btc);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_T0C + i, string_format("T%dC", i).c_str(), m_tc_12bit[i]);
+ state_add(ST_T4C, "T4C", m_t4c);
+ state_add(ST_TIEN, "TIEN", m_tien);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_FIFOS0 + i, string_format("FIFOS%d", i).c_str(), m_fifo_filled[i]).mask(0x1f);
+ state_add(ST_PSGC, "PSGC", m_psgc);
+ state_add(ST_PSGM, "PSGM", m_psgm);
+ for (int i = 0; i < 4; i++)
+ state_add(ST_VOL0 + i, string_format("VOL%d", i).c_str(), m_psg_vol[i]).mask(0xbf);
+ state_add(ST_VOLM0, "VOLM0", m_psg_volm[0]).mask(0x3f);
+ state_add(ST_VOLM1, "VOLM1", m_psg_volm[1]).mask(0x7f);
+ state_add(ST_MUL, "MUL", m_mul);
+ state_add(ST_SCTR, "SCTR", m_sctr);
+ state_add(ST_SCKR, "SCKR", m_sckr).mask(0x7f);
+ state_add(ST_SSR, "SSR", m_ssr).mask(0x77);
+ state_add(ST_SMOD, "SMOD", m_smod).mask(0x0f);
+ for (int i = 0; i < 2; i++)
+ {
+ state_add(ST_DMS0 + i, string_format("DMS%d", i).c_str(), m_dptr[i * 2]).mask(0x7fff);
+ state_add(ST_DMD0 + i, string_format("DMD%d", i).c_str(), m_dptr[i * 2 + 1]).mask(0x7fff);
+ state_add(ST_DBKS0 + i, string_format("DBKS%d", i).c_str(), m_dbkr[i * 2]).mask(0x87ff);
+ state_add(ST_DBKD0 + i, string_format("DBKD%d", i).c_str(), m_dbkr[i * 2 + 1]).mask(0x87ff);
+ state_add(ST_DCNT0 + i, string_format("DCNT%d", i).c_str(), m_dcnt[i]).mask(0x7fff);
+ state_add(ST_DMOD0 + i, string_format("DMOD%d", i).c_str(), m_dmod[i]).mask(0x3f);
+ }
+ state_add(ST_DCTR, "DCTR", m_dctr).mask(0x03);
+ state_add(ST_RCTR, "RCTR", m_rctr).mask(0xef);
+ state_add(ST_LVCTR, "LVCTR", m_lvctr).mask(0x0f);
+}
+
+void st2205u_base_device::device_reset()
+{
+ st2xxx_device::device_reset();
+
+ m_btc = 0;
+
+ std::fill(std::begin(m_tc_12bit), std::end(m_tc_12bit), 0);
+ std::fill(std::begin(m_count_12bit), std::end(m_count_12bit), 0);
+ for (auto &timer : m_timer_12bit)
+ timer->adjust(attotime::never);
+ m_t4c = 0;
+ m_tien = 0;
+
+ std::fill(std::begin(m_fifo_filled), std::end(m_fifo_filled), 0);
+ std::fill(std::begin(m_fifo_pos), std::end(m_fifo_pos), 0);
+ m_psgc = 0;
+ m_psgm = 0;
+ m_psg_on = 0;
+ std::fill(std::begin(m_psg_vol), std::end(m_psg_vol), 0);
+ std::fill(std::begin(m_psg_volm), std::end(m_psg_volm), 0);
+ m_mul = 0;
+
+ m_usbcon = 0;
+ m_usbien = 0x20;
+
+ std::fill(std::begin(m_dptr), std::end(m_dptr), 0);
+ std::fill(std::begin(m_dbkr), std::end(m_dbkr), 0);
+ std::fill(std::begin(m_dcnt), std::end(m_dcnt), 0);
+ m_dctr = 0;
+ std::fill(std::begin(m_dmod), std::end(m_dmod), 0);
+
+ m_rctr = 0;
+
+ m_lvctr = 0;
+
+ std::fill(std::begin(m_adpcm_level), std::end(m_adpcm_level), 0);
+ std::fill(std::begin(m_psg_amplitude), std::end(m_psg_amplitude), 0);
+ std::fill(std::begin(m_psg_freqcntr), std::end(m_psg_freqcntr), 0);
+}
+
+void st2205u_device::device_reset()
+{
+ st2205u_base_device::device_reset();
+
+ downcast<mi_st2205u &>(*mintf).brr = 0;
+
+ m_lbuf = 0;
+ m_lpal_index = 0;
+ std::fill(std::begin(m_gray_levels), std::end(m_gray_levels), 0);
+}
+
+const char *st2205u_device::st2xxx_irq_name(int i) const
+{
+ switch (i)
+ {
+ case 0: return "PE0/1/2 edge";
+ case 1: return "Timer 0";
+ case 2: return "Timer 1";
+ case 3: return "Timer 2";
+ case 4: return "Timer 3";
+ case 5: return "PA transition";
+ case 6: return "Base timer";
+ case 7: return "LCD buffer";
+ case 8: return "SPI TX empty";
+ case 9: return "SPI RX ready";
+ case 10: return "UART TX";
+ case 11: return "UART RX";
+ case 12: return "USB";
+ case 14: return "PCM";
+ case 15: return "RTC";
+ default: return "Reserved";
+ }
+}
+
+const char *st2302u_device::st2xxx_irq_name(int i) const
+{
+ switch (i)
+ {
+ case 0: return "P?0/1/2/3 edge";
+ case 1: return "Timer 0";
+ case 2: return "Timer 1";
+ case 3: return "Timer 2";
+ case 4: return "Timer 3";
+ case 5: return "PA transition";
+ case 6: return "Base timer";
+ case 8: return "SPI TX empty";
+ case 9: return "SPI RX ready";
+ case 12: return "USB";
+ case 14: return "PCM";
+ case 15: return "RTC";
+ default: return "Reserved";
+ }
+}
+
+u8 st2205u_device::mi_st2205u::pread(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ if (BIT(bank, 15))
+ return ram[0x4000 | (adr & 0x3fff)];
+ else
+ return data.read_byte(u32(bank) << 14 | (adr & 0x3fff));
+}
+
+u8 st2205u_device::mi_st2205u::preadc(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ if (BIT(bank, 15))
+ return ram[0x4000 | (adr & 0x3fff)];
+ else
+ return dcache.read_byte(u32(bank) << 14 | (adr & 0x3fff));
+}
+
+void st2205u_device::mi_st2205u::pwrite(u16 adr, u8 val)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ if (BIT(bank, 15))
+ ram[0x4000 | (adr & 0x3fff)] = val;
+ else
+ data.write_byte(u32(bank) << 14 | (adr & 0x3fff), val);
+}
+
+u8 st2205u_device::mi_st2205u::dread(u16 adr)
+{
+ if (BIT(drr, 15))
+ return ram[adr & 0x7fff];
+ else
+ return data.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+u8 st2205u_device::mi_st2205u::dreadc(u16 adr)
+{
+ if (BIT(drr, 15))
+ return ram[adr & 0x7fff];
+ else
+ return dcache.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+void st2205u_device::mi_st2205u::dwrite(u16 adr, u8 val)
+{
+ if (BIT(drr, 15))
+ ram[adr & 0x7fff] = val;
+ else
+ data.write_byte(u32(drr) << 15 | (adr & 0x7fff), val);
+}
+
+u8 st2205u_device::mi_st2205u::bread(u16 adr)
+{
+ if (BIT(brr, 15))
+ return ram[0x2000 | (adr & 0x1fff)];
+ else
+ return data.read_byte(u32(brr) << 13 | (adr & 0x1fff));
+}
+
+u8 st2205u_device::mi_st2205u::breadc(u16 adr)
+{
+ if (BIT(brr, 15))
+ return ram[0x2000 | (adr & 0x1fff)];
+ else
+ return dcache.read_byte(u32(brr) << 13 | (adr & 0x1fff));
+}
+
+void st2205u_device::mi_st2205u::bwrite(u16 adr, u8 val)
+{
+ if (BIT(brr, 15))
+ ram[0x2000 | (adr & 0x1fff)] = val;
+ else
+ data.write_byte(u32(brr) << 13 | (adr & 0x1fff), val);
+}
+
+u8 st2302u_device::mi_st2302u::pread(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return data.read_byte(u32(bank) << 14 | (adr & 0x3fff));
+}
+
+u8 st2302u_device::mi_st2302u::preadc(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return dcache.read_byte(u32(bank) << 14 | (adr & 0x3fff));
+}
+
+void st2302u_device::mi_st2302u::pwrite(u16 adr, u8 val)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ data.write_byte(u32(bank) << 14 | (adr & 0x3fff), val);
+}
+
+u8 st2302u_device::mi_st2302u::dread(u16 adr)
+{
+ return data.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+u8 st2302u_device::mi_st2302u::dreadc(u16 adr)
+{
+ return dcache.read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+void st2302u_device::mi_st2302u::dwrite(u16 adr, u8 val)
+{
+ data.write_byte(u32(drr) << 15 | (adr & 0x7fff), val);
+}
+
+u8 st2205u_device::mi_st2205u::read(u16 adr)
+{
+ return program.read_byte(adr);
+}
+
+u8 st2205u_device::mi_st2205u::read_sync(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : BIT(adr, 13) ? breadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2205u_device::mi_st2205u::read_arg(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : BIT(adr, 13) ? breadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2205u_device::mi_st2205u::read_vector(u16 adr)
+{
+ return pread(adr);
+}
+
+void st2205u_device::mi_st2205u::write(u16 adr, u8 val)
+{
+ program.write_byte(adr, val);
+}
+
+u8 st2302u_device::mi_st2302u::read(u16 adr)
+{
+ return program.read_byte(adr);
+}
+
+u8 st2302u_device::mi_st2302u::read_sync(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2302u_device::mi_st2302u::read_arg(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cprogram.read_byte(adr);
+}
+
+u8 st2302u_device::mi_st2302u::read_vector(u16 adr)
+{
+ return pread(adr);
+}
+
+void st2302u_device::mi_st2302u::write(u16 adr, u8 val)
+{
+ program.write_byte(adr, val);
+}
+
+u8 st2205u_device::brrl_r()
+{
+ return downcast<mi_st2205u &>(*mintf).brr & 0xff;
+}
+
+void st2205u_device::brrl_w(u8 data)
+{
+ u16 &brr = downcast<mi_st2205u &>(*mintf).brr;
+ brr = data | (brr & 0x9f00);
+}
+
+u8 st2205u_device::brrh_r()
+{
+ return downcast<mi_st2205u &>(*mintf).brr >> 8;
+}
+
+void st2205u_device::brrh_w(u8 data)
+{
+ u16 &brr = downcast<mi_st2205u &>(*mintf).brr;
+ brr = (data & 0x9f) << 8 | (brr & 0x00ff);
+}
+
+unsigned st2205u_base_device::st2xxx_bt_divider(int n) const
+{
+ // 2 Hz
+ if (n == 0)
+ return 16384;
+
+ // 32 Hz, 64 Hz, 128 Hz, 256 Hz, 512 Hz
+ if (n <= 5)
+ return 2048 >> n;
+
+ // 2048 Hz
+ if (n == 6)
+ return 16;
+
+ // 8192 Hz / BTC
+ assert(n == 7);
+ return 4 * (m_btc != 0 ? m_btc : 256);
+}
+
+u8 st2205u_base_device::btc_r()
+{
+ return m_btc;
+}
+
+void st2205u_base_device::btc_w(u8 data)
+{
+ m_btc = data;
+}
+
+u8 st2205u_base_device::psg_r(offs_t offset)
+{
+ u8 index = m_fifo_pos[offset >> 1];
+ if (BIT(offset, 0))
+ {
+ bool fwra = m_fifo_filled[offset >> 1] < 8;
+ return (m_dac_fifo[offset >> 1][index] & 0x100) >> 1 | (fwra ? 0x60 : 0x40) | m_fifo_filled[offset >> 1];
+ }
+ else
+ return m_dac_fifo[offset >> 1][index] & 0xff;
+}
+
+void st2205u_base_device::psg_w(offs_t offset, u8 data)
+{
+ if (m_fifo_filled[offset >> 1] < 16)
+ {
+ u8 index = (m_fifo_pos[offset >> 1] + m_fifo_filled[offset >> 1]++) & 15;
+ m_dac_fifo[offset >> 1][index] = data | (BIT(offset, 0) ? 0x100 : 0);
+ }
+}
+
+u8 st2205u_base_device::psgc_r()
+{
+ return m_psgc;
+}
+
+void st2205u_base_device::psgc_w(u8 data)
+{
+ m_psgc = data;
+ m_psg_on &= (data & 0xf0) >> 4;
+}
+
+u8 st2205u_base_device::psgm_r()
+{
+ return m_psgm;
+}
+
+void st2205u_base_device::psgm_w(u8 data)
+{
+ m_psgm = data;
+}
+
+u8 st2205u_base_device::vol_r(offs_t offset)
+{
+ return m_psg_vol[offset] | 0x40;
+}
+
+void st2205u_base_device::vol_w(offs_t offset, u8 data)
+{
+ m_psg_vol[offset] = data & 0xbf;
+}
+
+u8 st2205u_base_device::volm_r(offs_t offset)
+{
+ return m_psg_volm[offset] | (offset == 1 ? 0x80 : 0xc0);
+}
+
+void st2205u_base_device::volm_w(offs_t offset, u8 data)
+{
+ m_psg_volm[offset] = data & (offset == 1 ? 0x7f : 0x3f);
+}
+
+void st2205u_base_device::st2xxx_tclk_start()
+{
+ for (int t = 0; t < 4; t++)
+ if (BIT(m_tien, t) && (m_tc_12bit[t] & 0x7000) < 0x6000)
+ timer_start_from_tclk(t);
+}
+
+void st2205u_base_device::st2xxx_tclk_stop()
+{
+ for (int t = 0; t < 4; t++)
+ {
+ if (BIT(m_tien, t) && (m_tc_12bit[t] & 0x7000) < 0x6000)
+ {
+ m_count_12bit[t] = timer_12bit_count(t);
+ m_timer_12bit[t]->adjust(attotime::never);
+ }
+ }
+}
+
+u32 st2205u_base_device::tclk_pres_div(u8 mode) const
+{
+ assert(mode < 6);
+
+ // dphh8630 game 17 "Gang Nam Style" uses mode 0 for ADPCM music and if a 32Mhz clock is used, requires a divider of 1
+ // alternatively the divider can remain as 2 if the code in timer_12bit_process processes the FIFO every call instead
+ // of toggling it with m_psg_on, which is correct?
+ const int divtable[8] = { 1, 4, 8, 32, 1024, 4096, 4096, 4096 };
+
+ return divtable[mode];
+}
+
+TIMER_CALLBACK_MEMBER(st2205u_base_device::t0_interrupt)
+{
+ timer_12bit_process(0);
+}
+
+TIMER_CALLBACK_MEMBER(st2205u_base_device::t1_interrupt)
+{
+ timer_12bit_process(1);
+}
+
+TIMER_CALLBACK_MEMBER(st2205u_base_device::t2_interrupt)
+{
+ timer_12bit_process(2);
+}
+
+TIMER_CALLBACK_MEMBER(st2205u_base_device::t3_interrupt)
+{
+ timer_12bit_process(3);
+}
+
+void st2205u_base_device::push_adpcm_value(int channel, u16 psg_data)
+{
+ // the ADPCM often ends up off-center before samples are played
+ // is the FIFO hookup causing non-ADPCM data to be processed as ADPCM
+ // if mode changes in m_psgm aren't in sync with the FIFO output?
+
+ m_stream->update();
+
+ if (BIT(psg_data, 8))
+ m_adpcm_level[channel] -= psg_data & 0xff;
+ else
+ m_adpcm_level[channel] += psg_data & 0xff;
+
+ LOGDAC("Playing ADPCM sample %c%02X on channel %d (new level is %04x)\n", BIT(psg_data, 8) ? '-' : '+', psg_data & 0xff, channel, m_adpcm_level[channel]);
+}
+
+void st2205u_base_device::reset_adpcm_value(int channel)
+{
+ m_stream->update();
+
+ m_adpcm_level[channel] = 0;
+}
+
+void st2205u_base_device::timer_12bit_process(int t)
+{
+ if (BIT(m_psgc, t + 4))
+ {
+ if (BIT(m_psg_on, t))
+ m_psg_on &= ~(1 << t);
+ else if (m_fifo_filled[t] != 0)
+ {
+ m_psg_on |= 1 << t;
+
+ u16 psg_data = m_dac_fifo[t][m_fifo_pos[t]];
+ if (BIT(m_psgm, 2 * t + 1))
+ {
+ push_adpcm_value(t, psg_data);
+ }
+ else
+ {
+ reset_adpcm_value(t);
+ LOGDAC("Playing %s sample %02X on channel %d\n", BIT(m_psgm, 2 * t) ? "tone" : "DAC", psg_data & 0xff, t);
+
+ m_psg_amplitude[t] = psg_data & 0xff; // amplitude is controller by the data writes
+ m_psg_freqcntr[t] += 0x80; // the frequency is determined by the timer speed (there must be a better way to do this?)
+ }
+
+ --m_fifo_filled[t];
+ m_fifo_pos[t] = (m_fifo_pos[t] + 1) & 15;
+ }
+ }
+ // TODO: PCM has its own FIFO
+
+ // Timer interrupt is triggered when FIFO has more than 8 empty bytes
+ if (m_fifo_filled[t] < 8)
+ {
+ m_ireq |= 0x0002 << t;
+ update_irq_state();
+ }
+
+ // Bit 7 of TnCH allows auto-reload
+ m_count_12bit[t] = BIT(m_tc_12bit[t], 15) ? m_tc_12bit[t] & 0x0fff : 0;
+
+ u8 tck = (m_tc_12bit[t] & 0x7000) >> 12;
+ if (tck < 6)
+ m_timer_12bit[t]->adjust(cycles_to_attotime((0x1000 - m_count_12bit[t]) * tclk_pres_div(tck)));
+ else if (tck == 7 && BIT(t, 0))
+ m_timer_12bit[t]->adjust(attotime::from_ticks(0x1000 - m_count_12bit[t], 32768));
+
+ // TODO: BGRCK & INTX sources
+}
+
+u16 st2205u_base_device::timer_12bit_count(int t) const
+{
+ u16 count = m_count_12bit[t];
+ if (BIT(m_tien, t))
+ {
+ u8 tck = (m_tc_12bit[t] & 0x7000) >> 12;
+ if (BIT(m_prs, 6) && tck < 6)
+ count = 0x0fff - (attotime_to_cycles(m_timer_12bit[t]->remaining()) / tclk_pres_div(tck));
+ else if (tck == 7 && BIT(t, 0))
+ count = 0x0fff - m_timer_12bit[t]->remaining().as_ticks(32768);
+ }
+
+ return count & 0x0fff;
+}
+
+void st2205u_base_device::timer_start_from_tclk(int t)
+{
+ u32 div = tclk_pres_div((m_tc_12bit[t] & 0x7000) >> 12);
+ m_timer_12bit[t]->adjust(cycles_to_attotime((0x0fff - m_count_12bit[t]) * div + div - (pres_count() & (div - 1))));
+}
+
+void st2205u_base_device::timer_start_from_oscx(int t)
+{
+ m_timer_12bit[t]->adjust(attotime::from_ticks(0x1000 - m_count_12bit[t], 32768));
+}
+
+u8 st2205u_base_device::tc_12bit_r(offs_t offset)
+{
+ if (BIT(offset, 0))
+ return (timer_12bit_count(offset >> 1) | (m_tc_12bit[offset >> 1] & 0xf000)) >> 8;
+ else
+ return timer_12bit_count(offset >> 1) & 0x00ff;
+}
+
+void st2205u_base_device::tc_12bit_w(offs_t offset, u8 data)
+{
+ if (BIT(offset, 0))
+ m_tc_12bit[offset >> 1] = (m_tc_12bit[offset >> 1] & 0x00ff) | u16(data) << 8;
+ else
+ m_tc_12bit[offset >> 1] = (m_tc_12bit[offset >> 1] & 0xff00) | data;
+}
+
+u8 st2205u_base_device::t4c_r()
+{
+ return m_t4c;
+}
+
+void st2205u_base_device::t4c_w(u8 data)
+{
+ m_t4c = data;
+}
+
+u8 st2205u_base_device::tien_r()
+{
+ return m_tien;
+}
+
+void st2205u_base_device::tien_w(u8 data)
+{
+ for (int t = 0; t < 4; t++)
+ {
+ if (BIT(m_tien, t) && !BIT(data, t))
+ {
+ m_count_12bit[t] = timer_12bit_count(t);
+ m_timer_12bit[t]->adjust(attotime::never);
+ }
+ else if (!BIT(m_tien, t) && BIT(data, t))
+ {
+ m_count_12bit[t] = m_tc_12bit[t] & 0x0fff;
+
+ u8 tck = (m_tc_12bit[t] & 0x7000) >> 12;
+ if (BIT(m_prs, 6) && tck < 6)
+ timer_start_from_tclk(t);
+ else if (tck == 7 && BIT(t, 0))
+ timer_start_from_oscx(t);
+ }
+ }
+
+ m_tien = data;
+}
+
+unsigned st2205u_device::st2xxx_lfr_clocks() const
+{
+ unsigned lcdcks = ((m_lxmax * 2 + m_lfra * 4) + 5) * (m_lymax ? m_lymax : 256) * ((m_lctr & 0x03) == 0 ? 2 : 4);
+
+ if ((m_lckr & 0x30) == 0x00 || (m_lckr & 0x30) == 0x30)
+ return lcdcks * std::max(((m_lckr & 0x0c) >> 2) * 8, 4);
+ else
+ return lcdcks * std::max((m_lckr & 0x0f) * 2, 1);
+}
+
+u8 st2205u_device::lbuf_r()
+{
+ return m_lbuf;
+}
+
+void st2205u_device::lbuf_w(u8 data)
+{
+ m_lbuf = data;
+}
+
+void st2205u_device::lpal_w(u8 data)
+{
+ u8 index = m_lpal_index++;
+ m_lpal_index &= 0x0f;
+ if ((m_lctr & 0x0c) == 0x04)
+ index = (m_lpwm & 0xc0) >> 4 | (index & 0x03);
+
+ m_gray_levels[index] = data & 0x1f;
+}
+
+u8 st2205u_base_device::usbcon_r()
+{
+ return m_usbcon | 0x03;
+}
+
+void st2205u_base_device::usbcon_w(u8 data)
+{
+ m_usbcon = data & 0xfc;
+}
+
+u8 st2205u_base_device::usbien_r()
+{
+ return m_usbien | 0x40;
+}
+
+void st2205u_base_device::usbien_w(u8 data)
+{
+ m_usbien = data & 0xbf;
+}
+
+u8 st2205u_base_device::dptrl_r()
+{
+ return m_dptr[m_dctr] & 0x00ff;
+}
+
+void st2205u_base_device::dptrl_w(u8 data)
+{
+ m_dptr[m_dctr] = (m_dptr[m_dctr] & 0x7f00) | data;
+}
+
+u8 st2205u_base_device::dptrh_r()
+{
+ return (m_dptr[m_dctr] >> 8) | 0x80;
+}
+
+void st2205u_base_device::dptrh_w(u8 data)
+{
+ m_dptr[m_dctr] = u16(data & 0x7f) << 8 | (m_dptr[m_dctr] & 0x00ff);
+}
+
+u8 st2205u_base_device::dbkrl_r()
+{
+ return m_dbkr[m_dctr] & 0x00ff;
+}
+
+void st2205u_base_device::dbkrl_w(u8 data)
+{
+ m_dbkr[m_dctr] = (m_dbkr[m_dctr] & 0x8700) | data;
+}
+
+u8 st2205u_base_device::dbkrh_r()
+{
+ return (m_dbkr[m_dctr] >> 8) | 0x78;
+}
+
+void st2205u_base_device::dbkrh_w(u8 data)
+{
+ m_dbkr[m_dctr] = u16(data & 0x87) << 8 | (m_dbkr[m_dctr] & 0x00ff);
+}
+
+u8 st2205u_base_device::dcntl_r()
+{
+ return m_dcnt[m_dctr >> 1] & 0x00ff;
+}
+
+void st2205u_base_device::dcntl_w(u8 data)
+{
+ m_dcnt[m_dctr >> 1] = (m_dcnt[m_dctr >> 1] & 0x7f00) | data;
+}
+
+u8 st2205u_base_device::dcnth_r()
+{
+ return (m_dcnt[m_dctr >> 1] >> 8) | 0x80;
+}
+
+void st2205u_base_device::dcnth_w(u8 data)
+{
+ m_dcnt[m_dctr >> 1] = (data & 0x7f) << 8 | (m_dcnt[m_dctr >> 1] & 0x00ff);
+
+ // start DMA
+ u16 srcp = m_dptr[m_dctr & 2];
+ u16 srcb = m_dbkr[m_dctr & 2];
+ u16 dstp = m_dptr[m_dctr | 1];
+ u16 dstb = m_dbkr[m_dctr | 1];
+ u16 count = m_dcnt[m_dctr >> 1] + 1;
+ const u8 mode = m_dmod[m_dctr >> 1];
+
+ LOGDMA("%s: DMA%d $%X bytes in mode $%02X from $%X (%s) to $%X (%s)\n",
+ machine().describe_context(),
+ m_dctr >> 1, count, mode,
+ srcp | (srcb & 0x7ff) << 15, BIT(srcb, 15) ? "RAM" : "ROM",
+ dstp | (dstb & 0x7ff) << 15, BIT(dstb, 15) ? "RAM" : "ROM");
+
+ // FIXME: DMA should be performed in the execution loop and consume bus cycles, not happen instantly
+ while (count-- != 0)
+ {
+ uint8_t data;
+ if (BIT(srcb, 15))
+ data = mintf->cprogram.read_byte(srcp); // FIXME: 0080-7FFF should be all RAM on ST2205U
+ else
+ data = downcast<mi_st2xxx &>(*mintf).dcache.read_byte(srcp | u32(srcb << 15));
+ if (!BIT(mode, 1))
+ {
+ if (srcp++ == 0x7fff)
+ {
+ srcp = 0;
+ srcb++;
+ }
+ }
+
+ // TODO: XOR/OR/AND logic for DMA0 three-cycle modes (different on ST23XX?)
+ if (BIT(dstb, 15))
+ mintf->cprogram.write_byte(dstp, data); // FIXME: 0080-7FFF should be all RAM on ST2205U
+ else
+ downcast<mi_st2xxx &>(*mintf).dcache.write_byte(dstp | u32(dstb << 15), data);
+ if (!BIT(mode, 3))
+ {
+ if (dstp++ == 0x7fff)
+ {
+ dstp = 0;
+ dstb++;
+ }
+ }
+ }
+
+ // update pointers for continue mode
+ if ((mode & 0x03) == 0x00)
+ {
+ m_dptr[m_dctr & 2] = srcp;
+ m_dbkr[m_dctr & 2] = srcb & 0x87ff;
+ }
+ if ((mode & 0x0c) == 0x00)
+ {
+ m_dptr[m_dctr | 1] = dstp;
+ m_dbkr[m_dctr | 1] = dstb & 0x87ff;
+ }
+}
+
+u8 st2205u_base_device::dctr_r()
+{
+ return m_dctr | 0xfc;
+}
+
+void st2205u_base_device::dctr_w(u8 data)
+{
+ m_dctr = data & 0x03;
+}
+
+u8 st2205u_base_device::dmod_r()
+{
+ return m_dmod[m_dctr >> 1] | 0xc0;
+}
+
+void st2205u_base_device::dmod_w(u8 data)
+{
+ m_dmod[m_dctr >> 1] = data & 0x3f;
+}
+
+u8 st2205u_base_device::rctr_r()
+{
+ return (m_rctr & 0xe0) | 0x10;
+}
+
+void st2205u_base_device::rctr_w(u8 data)
+{
+ m_rctr = data & 0xef;
+}
+
+u8 st2205u_base_device::lvctr_r()
+{
+ return m_lvctr | 0x01;
+}
+
+void st2205u_base_device::lvctr_w(u8 data)
+{
+ m_lvctr = data & 0x0f;
+}
+
+u8 st2205u_base_device::mull_r()
+{
+ return m_mul & 0x00ff;
+}
+
+void st2205u_base_device::mull_w(u8 data)
+{
+ // TODO: result loaded 6 cycles after multiplier is written
+ m_mul = (s32(s16(m_mul)) * s8(data)) >> 8;
+}
+
+u8 st2205u_base_device::mulh_r()
+{
+ return m_mul >> 8;
+}
+
+void st2205u_base_device::mulh_w(u8 data)
+{
+ // write low byte of multiplicand, then high byte
+ m_mul = u16(data) << 8 | m_mul >> 8;
+}
+
+void st2302u_device::unk18_w(u8 data)
+{
+ logerror("%s: Writing %02X to unknown register $18\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk6d_w(u8 data)
+{
+ // $6D is PCMH on ST2205U, but probably not here
+ logerror("%s: Writing %02X to unknown register $6D\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk6e_w(u8 data)
+{
+ // $6E is MULL on ST2205U, but definitely not here
+ logerror("%s: Writing %02X to unknown register $6E\n", machine().describe_context(), data);
+}
+
+u8 st2302u_device::unk7b_r()
+{
+ // code usually waits for bit 3 to set itself after writing #$01 to this address
+ return 0x08;
+}
+
+void st2302u_device::unk7b_w(u8 data)
+{
+ logerror("%s: Writing %02X to unknown register $7B\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk7c_w(u8 data)
+{
+ logerror("%s: Writing %02X to unknown register $7C\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk7d_w(u8 data)
+{
+ // usually written with #$05 after the $7B wait is over
+ logerror("%s: Writing %02X to unknown register $7D\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk7e_w(u8 data)
+{
+ // written in succession with $7F, sometimes several times
+ logerror("%s: Writing %02X to unknown register $7E\n", machine().describe_context(), data);
+}
+
+void st2302u_device::unk7f_w(u8 data)
+{
+ // written in succession with $7E, sometimes several times
+ logerror("%s: Writing %02X to unknown register $7F\n", machine().describe_context(), data);
+}
+
+u8 st2205u_device::ram_r(offs_t offset)
+{
+ return downcast<mi_st2205u &>(*mintf).ram[0x0080 + offset];
+}
+
+void st2205u_device::ram_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2205u &>(*mintf).ram[0x0080 + offset] = data;
+}
+
+u8 st2205u_device::pmem_r(offs_t offset)
+{
+ return downcast<mi_st2205u &>(*mintf).pread(offset);
+}
+
+void st2205u_device::pmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2205u &>(*mintf).pwrite(offset, data);
+}
+
+u8 st2205u_device::dmem_r(offs_t offset)
+{
+ return downcast<mi_st2205u &>(*mintf).dread(offset);
+}
+
+void st2205u_device::dmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2205u &>(*mintf).dwrite(offset, data);
+}
+
+u8 st2205u_device::bmem_r(offs_t offset)
+{
+ return downcast<mi_st2205u &>(*mintf).bread(offset);
+}
+
+void st2205u_device::bmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2205u &>(*mintf).bwrite(offset, data);
+}
+
+u8 st2302u_device::pmem_r(offs_t offset)
+{
+ return downcast<mi_st2302u &>(*mintf).pread(offset);
+}
+
+void st2302u_device::pmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2302u &>(*mintf).pwrite(offset, data);
+}
+
+u8 st2302u_device::dmem_r(offs_t offset)
+{
+ return downcast<mi_st2302u &>(*mintf).dread(offset);
+}
+
+void st2302u_device::dmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2302u &>(*mintf).dwrite(offset, data);
+}
+
+void st2205u_base_device::base_map(address_map &map)
+{
+ map(0x0020, 0x0027).rw(FUNC(st2205u_base_device::tc_12bit_r), FUNC(st2205u_base_device::tc_12bit_w));
+ map(0x0028, 0x0028).rw(FUNC(st2205u_base_device::tien_r), FUNC(st2205u_base_device::tien_w));
+ map(0x0029, 0x0029).rw(FUNC(st2205u_base_device::prs_r), FUNC(st2205u_base_device::prs_w));
+ map(0x002a, 0x002a).rw(FUNC(st2205u_base_device::bten_r), FUNC(st2205u_base_device::bten_w));
+ map(0x002b, 0x002b).rw(FUNC(st2205u_base_device::btsr_r), FUNC(st2205u_base_device::btclr_w));
+ map(0x002c, 0x002c).rw(FUNC(st2205u_base_device::btc_r), FUNC(st2205u_base_device::btc_w));
+ map(0x002d, 0x002d).rw(FUNC(st2205u_base_device::t4c_r), FUNC(st2205u_base_device::t4c_w));
+ map(0x002e, 0x002e).rw(FUNC(st2205u_base_device::rctr_r), FUNC(st2205u_base_device::rctr_w));
+ map(0x0030, 0x0030).rw(FUNC(st2205u_base_device::irrl_r), FUNC(st2205u_base_device::irrl_w));
+ map(0x0031, 0x0031).rw(FUNC(st2205u_base_device::irrh_r), FUNC(st2205u_base_device::irrh_w));
+ map(0x0032, 0x0032).rw(FUNC(st2205u_base_device::prrl_r), FUNC(st2205u_base_device::prrl_w));
+ map(0x0033, 0x0033).rw(FUNC(st2205u_base_device::prrh_r), FUNC(st2205u_base_device::prrh_w));
+ map(0x0034, 0x0034).rw(FUNC(st2205u_base_device::drrl_r), FUNC(st2205u_base_device::drrl_w));
+ map(0x0035, 0x0035).rw(FUNC(st2205u_base_device::drrh_r), FUNC(st2205u_base_device::drrh_w));
+ map(0x0038, 0x0038).rw(FUNC(st2205u_base_device::misc_r), FUNC(st2205u_base_device::misc_w));
+ map(0x0039, 0x0039).rw(FUNC(st2205u_base_device::sys_r), FUNC(st2205u_base_device::sys_w));
+ map(0x003c, 0x003c).rw(FUNC(st2205u_base_device::ireql_r), FUNC(st2205u_base_device::ireql_w));
+ map(0x003d, 0x003d).rw(FUNC(st2205u_base_device::ireqh_r), FUNC(st2205u_base_device::ireqh_w));
+ map(0x003e, 0x003e).rw(FUNC(st2205u_base_device::ienal_r), FUNC(st2205u_base_device::ienal_w));
+ map(0x003f, 0x003f).rw(FUNC(st2205u_base_device::ienah_r), FUNC(st2205u_base_device::ienah_w));
+ map(0x0058, 0x0058).rw(FUNC(st2205u_base_device::dptrl_r), FUNC(st2205u_base_device::dptrl_w));
+ map(0x0059, 0x0059).rw(FUNC(st2205u_base_device::dptrh_r), FUNC(st2205u_base_device::dptrh_w));
+ map(0x005a, 0x005a).rw(FUNC(st2205u_base_device::dbkrl_r), FUNC(st2205u_base_device::dbkrl_w));
+ map(0x005b, 0x005b).rw(FUNC(st2205u_base_device::dbkrh_r), FUNC(st2205u_base_device::dbkrh_w));
+ map(0x005c, 0x005c).rw(FUNC(st2205u_base_device::dcntl_r), FUNC(st2205u_base_device::dcntl_w));
+ map(0x005d, 0x005d).rw(FUNC(st2205u_base_device::dcnth_r), FUNC(st2205u_base_device::dcnth_w));
+ map(0x005e, 0x005e).rw(FUNC(st2205u_base_device::dctr_r), FUNC(st2205u_base_device::dctr_w));
+ map(0x005f, 0x005f).rw(FUNC(st2205u_base_device::dmod_r), FUNC(st2205u_base_device::dmod_w));
+ map(0x0070, 0x0070).rw(FUNC(st2205u_base_device::usbcon_r), FUNC(st2205u_base_device::usbcon_w));
+ map(0x0071, 0x0071).rw(FUNC(st2205u_base_device::usbien_r), FUNC(st2205u_base_device::usbien_w));
+}
+
+void st2205u_device::int_map(address_map &map)
+{
+ base_map(map);
+ map(0x0000, 0x0005).rw(FUNC(st2205u_device::pdata_r), FUNC(st2205u_device::pdata_w));
+ map(0x0006, 0x0006).rw(FUNC(st2205u_device::psc_r), FUNC(st2205u_device::psc_w));
+ map(0x0007, 0x0007).rw(FUNC(st2205u_device::pse_r), FUNC(st2205u_device::pse_w));
+ map(0x0008, 0x000d).rw(FUNC(st2205u_device::pctrl_r), FUNC(st2205u_device::pctrl_w));
+ map(0x000e, 0x000e).rw(FUNC(st2205u_device::pfc_r), FUNC(st2205u_device::pfc_w));
+ map(0x000f, 0x000f).rw(FUNC(st2205u_device::pfd_r), FUNC(st2205u_device::pfd_w));
+ map(0x0010, 0x0017).rw(FUNC(st2205u_device::psg_r), FUNC(st2205u_device::psg_w));
+ map(0x0018, 0x001b).rw(FUNC(st2205u_device::vol_r), FUNC(st2205u_device::vol_w));
+ map(0x001c, 0x001d).rw(FUNC(st2205u_device::volm_r), FUNC(st2205u_device::volm_w));
+ map(0x001e, 0x001e).rw(FUNC(st2205u_device::psgc_r), FUNC(st2205u_device::psgc_w));
+ map(0x001f, 0x001f).rw(FUNC(st2205u_device::psgm_r), FUNC(st2205u_device::psgm_w));
+ map(0x0036, 0x0036).rw(FUNC(st2205u_device::brrl_r), FUNC(st2205u_device::brrl_w));
+ map(0x0037, 0x0037).rw(FUNC(st2205u_device::brrh_r), FUNC(st2205u_device::brrh_w));
+ map(0x003a, 0x003a).rw(FUNC(st2205u_device::pmcr_r), FUNC(st2205u_device::pmcr_w));
+ map(0x0040, 0x0040).w(FUNC(st2205u_device::lssal_w));
+ map(0x0041, 0x0041).w(FUNC(st2205u_device::lssah_w));
+ map(0x0042, 0x0042).w(FUNC(st2205u_device::lvpw_w));
+ map(0x0043, 0x0043).rw(FUNC(st2205u_device::lxmax_r), FUNC(st2205u_device::lxmax_w));
+ map(0x0044, 0x0044).rw(FUNC(st2205u_device::lymax_r), FUNC(st2205u_device::lymax_w));
+ map(0x0045, 0x0045).rw(FUNC(st2205u_device::lpan_r), FUNC(st2205u_device::lpan_w));
+ map(0x0046, 0x0046).rw(FUNC(st2205u_device::lbuf_r), FUNC(st2205u_device::lbuf_w));
+ map(0x0047, 0x0047).rw(FUNC(st2205u_device::lctr_r), FUNC(st2205u_device::lctr_w));
+ map(0x0048, 0x0048).w(FUNC(st2205u_device::lckr_w));
+ map(0x0049, 0x0049).w(FUNC(st2205u_device::lfra_w));
+ map(0x004a, 0x004a).rw(FUNC(st2205u_device::lac_r), FUNC(st2205u_device::lac_w));
+ map(0x004b, 0x004b).rw(FUNC(st2205u_device::lpwm_r), FUNC(st2205u_device::lpwm_w));
+ map(0x004c, 0x004c).w(FUNC(st2205u_device::lpal_w));
+ map(0x004e, 0x004e).rw(FUNC(st2205u_device::pl_r), FUNC(st2205u_device::pl_w));
+ map(0x004f, 0x004f).rw(FUNC(st2205u_device::pcl_r), FUNC(st2205u_device::pcl_w));
+ map(0x0052, 0x0052).rw(FUNC(st2205u_device::sctr_r), FUNC(st2205u_device::sctr_w));
+ map(0x0053, 0x0053).rw(FUNC(st2205u_device::sckr_r), FUNC(st2205u_device::sckr_w));
+ map(0x0054, 0x0054).rw(FUNC(st2205u_device::ssr_r), FUNC(st2205u_device::ssr_w));
+ map(0x0055, 0x0055).rw(FUNC(st2205u_device::smod_r), FUNC(st2205u_device::smod_w));
+ map(0x0057, 0x0057).rw(FUNC(st2205u_device::lvctr_r), FUNC(st2205u_device::lvctr_w));
+ map(0x0060, 0x0060).rw(FUNC(st2205u_device::uctr_r), FUNC(st2205u_device::uctr_w));
+ map(0x0061, 0x0061).rw(FUNC(st2205u_device::usr_r), FUNC(st2205u_device::usr_clr_w));
+ map(0x0062, 0x0062).rw(FUNC(st2205u_device::irctr_r), FUNC(st2205u_device::irctr_w));
+ map(0x0063, 0x0063).rw(FUNC(st2205u_device::bctr_r), FUNC(st2205u_device::bctr_w));
+ map(0x0064, 0x0064).rw(FUNC(st2205u_device::udata_r), FUNC(st2205u_device::udata_w));
+ map(0x0066, 0x0066).rw(FUNC(st2205u_device::brs_r), FUNC(st2205u_device::brs_w));
+ map(0x0067, 0x0067).rw(FUNC(st2205u_device::bdiv_r), FUNC(st2205u_device::bdiv_w));
+ map(0x006e, 0x006e).rw(FUNC(st2205u_device::mull_r), FUNC(st2205u_device::mull_w));
+ map(0x006f, 0x006f).rw(FUNC(st2205u_device::mulh_r), FUNC(st2205u_device::mulh_w));
+ map(0x0080, 0x1fff).rw(FUNC(st2205u_device::ram_r), FUNC(st2205u_device::ram_w)); // assumed to be shared with banked RAM
+ map(0x2000, 0x3fff).rw(FUNC(st2205u_device::bmem_r), FUNC(st2205u_device::bmem_w));
+ map(0x4000, 0x7fff).rw(FUNC(st2205u_device::pmem_r), FUNC(st2205u_device::pmem_w));
+ map(0x8000, 0xffff).rw(FUNC(st2205u_device::dmem_r), FUNC(st2205u_device::dmem_w));
+}
+
+void st2302u_device::int_map(address_map &map)
+{
+ base_map(map);
+ map(0x0000, 0x0005).rw(FUNC(st2302u_device::pdata_r), FUNC(st2302u_device::pdata_w));
+ map(0x0006, 0x0006).rw(FUNC(st2302u_device::psc_r), FUNC(st2302u_device::psc_w));
+ map(0x0008, 0x000d).rw(FUNC(st2302u_device::pctrl_r), FUNC(st2302u_device::pctrl_w));
+ map(0x000e, 0x000e).rw(FUNC(st2302u_device::pfc_r), FUNC(st2302u_device::pfc_w));
+ map(0x000f, 0x000f).rw(FUNC(st2302u_device::pfd_r), FUNC(st2302u_device::pfd_w));
+ map(0x0012, 0x0012).rw(FUNC(st2302u_device::sctr_r), FUNC(st2302u_device::sctr_w));
+ map(0x0013, 0x0013).rw(FUNC(st2302u_device::sckr_r), FUNC(st2302u_device::sckr_w));
+ map(0x0014, 0x0014).rw(FUNC(st2302u_device::ssr_r), FUNC(st2302u_device::ssr_w));
+ map(0x0015, 0x0015).rw(FUNC(st2302u_device::smod_r), FUNC(st2302u_device::smod_w));
+ map(0x0016, 0x0016).rw(FUNC(st2302u_device::mull_r), FUNC(st2302u_device::mull_w));
+ map(0x0017, 0x0017).rw(FUNC(st2302u_device::mulh_r), FUNC(st2302u_device::mulh_w));
+ map(0x0018, 0x0018).w(FUNC(st2302u_device::unk18_w));
+ map(0x0040, 0x0047).rw(FUNC(st2302u_device::psg_r), FUNC(st2302u_device::psg_w));
+ map(0x0048, 0x004b).rw(FUNC(st2302u_device::vol_r), FUNC(st2302u_device::vol_w));
+ map(0x004c, 0x004d).rw(FUNC(st2302u_device::volm_r), FUNC(st2302u_device::volm_w));
+ map(0x004e, 0x004e).rw(FUNC(st2302u_device::psgc_r), FUNC(st2302u_device::psgc_w));
+ map(0x004f, 0x004f).rw(FUNC(st2302u_device::psgm_r), FUNC(st2302u_device::psgm_w));
+ map(0x006d, 0x006d).w(FUNC(st2302u_device::unk6d_w));
+ map(0x006e, 0x006e).w(FUNC(st2302u_device::unk6e_w));
+ map(0x007b, 0x007b).rw(FUNC(st2302u_device::unk7b_r), FUNC(st2302u_device::unk7b_w));
+ map(0x007c, 0x007c).w(FUNC(st2302u_device::unk7c_w));
+ map(0x007d, 0x007d).w(FUNC(st2302u_device::unk7d_w));
+ map(0x007e, 0x007e).w(FUNC(st2302u_device::unk7e_w));
+ map(0x007f, 0x007f).w(FUNC(st2302u_device::unk7f_w));
+ map(0x0080, 0x07ff).ram();
+ map(0x4000, 0x7fff).rw(FUNC(st2302u_device::pmem_r), FUNC(st2302u_device::pmem_w));
+ map(0x8000, 0xffff).rw(FUNC(st2302u_device::dmem_r), FUNC(st2302u_device::dmem_w));
+}
diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h
new file mode 100644
index 00000000000..cad10f08b3b
--- /dev/null
+++ b/src/devices/cpu/m6502/st2205u.h
@@ -0,0 +1,318 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2205U 8-Bit Integrated Microcontroller
+
+**********************************************************************/
+
+#ifndef MAME_CPU_M6502_ST2205U_H
+#define MAME_CPU_M6502_ST2205U_H
+
+#pragma once
+
+#include "st2xxx.h"
+
+class st2205u_base_device : public st2xxx_device, public device_sound_interface
+{
+public:
+ enum {
+ ST_BTC = ST_BDIV + 1,
+ ST_T0C,
+ ST_T1C,
+ ST_T2C,
+ ST_T3C,
+ ST_T4C,
+ ST_TIEN,
+ ST_FIFOS0,
+ ST_FIFOS1,
+ ST_FIFOS2,
+ ST_FIFOS3,
+ ST_PSGC,
+ ST_PSGM,
+ ST_VOL0,
+ ST_VOL1,
+ ST_VOL2,
+ ST_VOL3,
+ ST_VOLM0,
+ ST_VOLM1,
+ ST_MUL,
+ ST_DMS0,
+ ST_DMS1,
+ ST_DMD0,
+ ST_DMD1,
+ ST_DBKS0,
+ ST_DBKS1,
+ ST_DBKD0,
+ ST_DBKD1,
+ ST_DCNT0,
+ ST_DCNT1,
+ ST_DCTR,
+ ST_DMOD0,
+ ST_DMOD1,
+ ST_USBCON,
+ ST_USBIEN,
+ ST_RCTR,
+ ST_LVCTR
+ };
+
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
+protected:
+ st2205u_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram);
+
+ virtual void device_reset() override ATTR_COLD;
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream) override;
+
+ virtual unsigned st2xxx_bt_divider(int n) const override;
+ virtual u8 st2xxx_prs_mask() const override { return 0xc0; }
+ virtual void st2xxx_tclk_start() override;
+ virtual void st2xxx_tclk_stop() override;
+ virtual bool st2xxx_has_dma() const override { return true; }
+
+ void base_init(std::unique_ptr<mi_st2xxx> &&intf);
+
+ void push_adpcm_value(int channel, u16 psg_data);
+ void reset_adpcm_value(int channel);
+
+ u8 btc_r();
+ void btc_w(u8 data);
+ u32 tclk_pres_div(u8 mode) const;
+ TIMER_CALLBACK_MEMBER(t0_interrupt);
+ TIMER_CALLBACK_MEMBER(t1_interrupt);
+ TIMER_CALLBACK_MEMBER(t2_interrupt);
+ TIMER_CALLBACK_MEMBER(t3_interrupt);
+ void timer_12bit_process(int t);
+ u16 timer_12bit_count(int t) const;
+ void timer_start_from_tclk(int t);
+ void timer_start_from_oscx(int t);
+ u8 tc_12bit_r(offs_t offset);
+ void tc_12bit_w(offs_t offset, u8 data);
+ u8 t4c_r();
+ void t4c_w(u8 data);
+ u8 tien_r();
+ void tien_w(u8 data);
+
+ u8 psg_r(offs_t offset);
+ void psg_w(offs_t offset, u8 data);
+ u8 psgc_r();
+ void psgc_w(u8 data);
+ u8 psgm_r();
+ void psgm_w(u8 data);
+ u8 vol_r(offs_t offset);
+ void vol_w(offs_t offset, u8 data);
+ u8 volm_r(offs_t offset);
+ void volm_w(offs_t offset, u8 data);
+
+ u8 usbcon_r();
+ void usbcon_w(u8 data);
+ u8 usbien_r();
+ void usbien_w(u8 data);
+ u8 dptrl_r();
+ void dptrl_w(u8 data);
+ u8 dptrh_r();
+ void dptrh_w(u8 data);
+ u8 dbkrl_r();
+ void dbkrl_w(u8 data);
+ u8 dbkrh_r();
+ void dbkrh_w(u8 data);
+ u8 dcntl_r();
+ void dcntl_w(u8 data);
+ u8 dcnth_r();
+ void dcnth_w(u8 data);
+ u8 dctr_r();
+ void dctr_w(u8 data);
+ u8 dmod_r();
+ void dmod_w(u8 data);
+
+ u8 rctr_r();
+ void rctr_w(u8 data);
+
+ u8 lvctr_r();
+ void lvctr_w(u8 data);
+
+ u8 mull_r();
+ void mull_w(u8 data);
+ u8 mulh_r();
+ void mulh_w(u8 data);
+
+ void base_map(address_map &map) ATTR_COLD;
+
+ sound_stream *m_stream;
+
+ u8 m_btc;
+ u16 m_tc_12bit[4];
+ u16 m_count_12bit[4];
+ emu_timer *m_timer_12bit[4];
+ u8 m_t4c;
+ u8 m_tien;
+ u16 m_dac_fifo[4][16];
+ u8 m_fifo_filled[4];
+ u8 m_fifo_pos[4];
+ u8 m_psgc;
+ u8 m_psgm;
+ u8 m_psg_on;
+ u8 m_psg_vol[4];
+ u8 m_psg_volm[2];
+ u16 m_mul;
+ u8 m_usbcon;
+ u8 m_usbien;
+ u16 m_dptr[4];
+ u16 m_dbkr[4];
+ u16 m_dcnt[2];
+ u8 m_dctr;
+ u8 m_dmod[2];
+ u8 m_rctr;
+ u8 m_lvctr;
+
+ s16 m_adpcm_level[4];
+ u8 m_psg_amplitude[4];
+ u32 m_psg_freqcntr[4];
+};
+
+class st2205u_device : public st2205u_base_device
+{
+public:
+ enum {
+ ST_LBUF = ST_LVCTR + 1,
+ ST_BRR
+ };
+
+ st2205u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u16 st2xxx_ireq_mask() const override { return 0xdfff; }
+ virtual const char *st2xxx_irq_name(int i) const override;
+ virtual u8 st2xxx_pmcr_mask() const override { return 0xff; }
+ virtual u8 st2xxx_sys_mask() const override { return 0xfe; }
+ virtual u8 st2xxx_misc_mask() const override { return 0x0f; }
+ virtual bool st2xxx_wdten_on_reset() const override { return true; }
+ virtual u8 st2xxx_lpan_mask() const override { return 0x0f; }
+ virtual u8 st2xxx_lctr_mask() const override { return 0xef; }
+ virtual u8 st2xxx_lckr_mask() const override { return 0x3f; }
+ virtual u8 st2xxx_lpwm_mask() const override { return 0xff; }
+ virtual unsigned st2xxx_lfr_clocks() const override;
+ virtual bool st2xxx_has_spi() const override { return true; }
+ virtual bool st2xxx_spi_iis() const override { return true; }
+ virtual u8 st2xxx_uctr_mask() const override { return 0x3f; }
+ virtual u8 st2xxx_bctr_mask() const override { return 0xb7; }
+
+private:
+ class mi_st2205u : public mi_st2xxx {
+ public:
+ virtual u8 read(u16 adr) override;
+ virtual u8 read_sync(u16 adr) override;
+ virtual u8 read_arg(u16 adr) override;
+ virtual u8 read_vector(u16 adr) override;
+ virtual void write(u16 adr, u8 val) override;
+
+ u8 pread(u16 adr);
+ u8 preadc(u16 adr);
+ void pwrite(u16 adr, u8 val);
+ u8 dread(u16 adr);
+ u8 dreadc(u16 adr);
+ void dwrite(u16 adr, u8 val);
+ u8 bread(u16 adr);
+ u8 breadc(u16 adr);
+ void bwrite(u16 adr, u8 val);
+
+ u16 brr;
+
+ std::unique_ptr<u8[]> ram;
+ };
+
+ u8 brrl_r();
+ void brrl_w(u8 data);
+ u8 brrh_r();
+ void brrh_w(u8 data);
+
+ u8 lbuf_r();
+ void lbuf_w(u8 data);
+ void lpal_w(u8 data);
+
+ u8 ram_r(offs_t offset);
+ void ram_w(offs_t offset, u8 data);
+ u8 pmem_r(offs_t offset);
+ void pmem_w(offs_t offset, u8 data);
+ u8 dmem_r(offs_t offset);
+ void dmem_w(offs_t offset, u8 data);
+ u8 bmem_r(offs_t offset);
+ void bmem_w(offs_t offset, u8 data);
+
+ void int_map(address_map &map) ATTR_COLD;
+
+ u8 m_lbuf;
+ u8 m_lpal_index;
+ u8 m_gray_levels[16];
+};
+
+class st2302u_device : public st2205u_base_device
+{
+public:
+ st2302u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ virtual u16 st2xxx_ireq_mask() const override { return 0xd37f; } // ???
+ virtual const char *st2xxx_irq_name(int i) const override;
+ virtual u8 st2xxx_pmcr_mask() const override { return 0xff; } // ???
+ virtual u8 st2xxx_sys_mask() const override { return 0xfe; } // ???
+ virtual u8 st2xxx_misc_mask() const override { return 0x0f; } // ???
+ virtual bool st2xxx_wdten_on_reset() const override { return true; } // ???
+ virtual u8 st2xxx_lpan_mask() const override { return 0; } // no LCDC
+ virtual u8 st2xxx_lctr_mask() const override { return 0; } // no LCDC
+ virtual u8 st2xxx_lckr_mask() const override { return 0; } // no LCDC
+ virtual u8 st2xxx_lpwm_mask() const override { return 0; } // no LCDC
+ virtual unsigned st2xxx_lfr_clocks() const override { return 0; } // no LCDC
+ virtual bool st2xxx_has_spi() const override { return true; }
+ virtual bool st2xxx_spi_iis() const override { return true; }
+ virtual u8 st2xxx_uctr_mask() const override { return 0; } // no UART
+ virtual u8 st2xxx_bctr_mask() const override { return 0; } // no UART
+
+private:
+ class mi_st2302u : public mi_st2xxx {
+ public:
+ virtual u8 read(u16 adr) override;
+ virtual u8 read_sync(u16 adr) override;
+ virtual u8 read_arg(u16 adr) override;
+ virtual u8 read_vector(u16 adr) override;
+ virtual void write(u16 adr, u8 val) override;
+
+ u8 pread(u16 adr);
+ u8 preadc(u16 adr);
+ void pwrite(u16 adr, u8 val);
+ u8 dread(u16 adr);
+ u8 dreadc(u16 adr);
+ void dwrite(u16 adr, u8 val);
+ };
+
+ void unk18_w(u8 data);
+ void unk6d_w(u8 data);
+ void unk6e_w(u8 data);
+ u8 unk7b_r();
+ void unk7b_w(u8 data);
+ void unk7c_w(u8 data);
+ void unk7d_w(u8 data);
+ void unk7e_w(u8 data);
+ void unk7f_w(u8 data);
+
+ u8 ram_r(offs_t offset);
+ void ram_w(offs_t offset, u8 data);
+ u8 pmem_r(offs_t offset);
+ void pmem_w(offs_t offset, u8 data);
+ u8 dmem_r(offs_t offset);
+ void dmem_w(offs_t offset, u8 data);
+
+ void int_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(ST2205U, st2205u_device)
+DECLARE_DEVICE_TYPE(ST2302U, st2302u_device)
+
+#endif // MAME_MACHINE_M6502_ST2205U_H
diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp
new file mode 100644
index 00000000000..4dbaf96b3b3
--- /dev/null
+++ b/src/devices/cpu/m6502/st2xxx.cpp
@@ -0,0 +1,914 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2XXX LCD MCUs
+
+ This extended SoC family combines a W65C02S 8-bit CPU core
+ (including the Rockwell bit opcodes) with a wide variety of on-
+ chip peripherals. Common features besides internal RAM and ROM are
+ parallel ports, internal timers, a vectored interrupt controller,
+ LCD controllers (of varying degrees of sophistication), R/C/slow
+ XTAL clock generators, power management and PSG channels for
+ speaker output. Each MCU also has numerous pins dedicated to LCD
+ segment drivers (ST20XX, ST2104, ST2108), an external bus capable
+ of addressing several MB of off-chip memory using multiple chip
+ select signals (ST2100, ST22XX), or both (ST25XX, ST26XX). The
+ later ST23XX series, targeted mostly at digital greeting card
+ applications, eliminated on-chip LCD control but retained other
+ typical ST2XXX features.
+
+ On all ST2XXX MCUs but the smallest single-chip ST20XX models,
+ 4000–7FFF (nominally program memory) and 8000–FFFF (nominally
+ data memory) are bankswitched over all internal and external ROM,
+ and interrupt vectors are read from 7Fxx rather than FFxx. The
+ ST22XX and ST26XX series use a separate, auto-incrementing bank
+ register for DMA reads from the 8000–FFFF area, and will also
+ switch 4000–7FFF to a different bank during interrupt service if
+ the IRREN bit in the SYS register is set.
+
+ At some time between 2010 and 2012, Sitronix spun off all of its
+ SoC product line to mCore Technology Corporation.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "st2xxx.h"
+
+#define LOG_IRQ (1U << 1)
+#define LOG_BT (1U << 2)
+#define LOG_LCDC (1U << 3)
+#define VERBOSE LOG_IRQ
+//#define VERBOSE (LOG_IRQ | LOG_BT | LOG_LCDC)
+#include "logmacro.h"
+
+st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram)
+ : w65c02s_device(mconfig, type, tag, owner, clock)
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, data_bits, 0)
+ , m_in_port_cb(*this, 0xff)
+ , m_out_port_cb(*this)
+ , m_prr_mask(data_bits <= 14 ? 0 : ((u16(1) << (data_bits - 14)) - 1) | (has_banked_ram ? 0x8000 : 0))
+ , m_drr_mask(data_bits <= 15 ? 0 : ((u16(1) << (data_bits - 15)) - 1) | (has_banked_ram ? 0x8000 : 0))
+ , m_pdata{0}
+ , m_pctrl{0}
+ , m_psel{0}
+ , m_pfun{0}
+ , m_pmcr(0)
+ , m_bten(0)
+ , m_btsr(0)
+ , m_bt_mask(0)
+ , m_bt_ireq(0)
+ , m_pres_base(0)
+ , m_pres_started(attotime::zero)
+ , m_prs(0)
+ , m_sys(0)
+ , m_misc(0)
+ , m_ireq(0)
+ , m_iena(0)
+ , m_irq_level(0xff)
+ , m_lssa(0)
+ , m_lvpw(0)
+ , m_lxmax(0)
+ , m_lymax(0)
+ , m_lpan(0)
+ , m_lctr(0)
+ , m_lckr(0)
+ , m_lfra(0)
+ , m_lac(0)
+ , m_lpwm(0)
+ , m_lcd_ireq(0)
+ , m_lcd_timer(nullptr)
+ , m_sctr(0)
+ , m_sckr(0)
+ , m_ssr(0)
+ , m_smod(0)
+ , m_uctr(0)
+ , m_usr(0)
+ , m_irctr(0)
+ , m_bctr(0)
+{
+ program_config.m_internal_map = std::move(internal_map);
+}
+
+device_memory_interface::space_config_vector st2xxx_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &program_config),
+ std::make_pair(AS_DATA, &m_data_config)
+ };
+}
+
+TIMER_CALLBACK_MEMBER(st2xxx_device::bt_interrupt)
+{
+ // BTSR must be cleared each time the interrupt is serviced
+ bool interrupt = (m_btsr == 0);
+
+ m_btsr |= 1 << param;
+
+ unsigned div = st2xxx_bt_divider(param);
+ assert(div != 0);
+ m_base_timer[param]->adjust(attotime::from_ticks(div, 32768), param);
+
+ if (interrupt)
+ {
+ LOGMASKED(LOG_BT, "Interrupt caused by %.1f Hz base timer\n", 32768.0 / div);
+ m_ireq |= m_bt_ireq;
+ update_irq_state();
+ }
+}
+
+void st2xxx_device::init_base_timer(u16 ireq)
+{
+ m_bt_ireq = ireq;
+
+ for (int n = 0; n < 8; n++)
+ {
+ if (st2xxx_bt_divider(n) != 0)
+ {
+ m_bt_mask |= 1 << n;
+ m_base_timer[n] = timer_alloc(FUNC(st2xxx_device::bt_interrupt), this);
+ }
+ }
+
+ assert(m_bt_mask != 0);
+ assert(m_bt_ireq != 0);
+}
+
+TIMER_CALLBACK_MEMBER(st2xxx_device::lcd_interrupt)
+{
+ m_ireq |= m_lcd_ireq;
+ update_irq_state();
+}
+
+void st2xxx_device::init_lcd_timer(u16 ireq)
+{
+ m_lcd_ireq = ireq;
+ assert(m_lcd_ireq != 0);
+
+ m_lcd_timer = timer_alloc(FUNC(st2xxx_device::lcd_interrupt), this);
+}
+
+void st2xxx_device::save_common_registers()
+{
+ mi_st2xxx *intf = downcast<mi_st2xxx *>(mintf.get());
+
+ save_item(NAME(m_pdata));
+ save_item(NAME(m_pctrl));
+ save_item(NAME(m_psel));
+ save_item(NAME(m_pfun));
+ save_item(NAME(m_pmcr));
+ if (m_prr_mask != 0)
+ {
+ if (BIT(st2xxx_sys_mask(), 1))
+ {
+ save_item(NAME(intf->irq_service));
+ save_item(NAME(intf->irr_enable));
+ save_item(NAME(intf->irr));
+ }
+ save_item(NAME(intf->prr));
+ }
+ if (m_drr_mask != 0)
+ save_item(NAME(intf->drr));
+ if (m_bt_mask != 0)
+ {
+ save_item(NAME(m_bten));
+ save_item(NAME(m_btsr));
+ }
+ save_item(NAME(m_pres_base));
+ save_item(NAME(m_pres_started));
+ save_item(NAME(m_prs));
+ save_item(NAME(m_sys));
+ if (st2xxx_misc_mask() != 0)
+ save_item(NAME(m_misc));
+ save_item(NAME(m_ireq));
+ save_item(NAME(m_iena));
+ save_item(NAME(m_irq_level));
+ if (st2xxx_lctr_mask() != 0)
+ {
+ save_item(NAME(m_lssa));
+ save_item(NAME(m_lvpw));
+ save_item(NAME(m_lxmax));
+ save_item(NAME(m_lymax));
+ if (st2xxx_lpan_mask() != 0)
+ save_item(NAME(m_lpan));
+ save_item(NAME(m_lctr));
+ save_item(NAME(m_lckr));
+ save_item(NAME(m_lfra));
+ save_item(NAME(m_lac));
+ save_item(NAME(m_lpwm));
+ }
+ if (st2xxx_has_spi())
+ {
+ save_item(NAME(m_sctr));
+ save_item(NAME(m_sckr));
+ save_item(NAME(m_ssr));
+ if (st2xxx_spi_iis())
+ save_item(NAME(m_smod));
+ }
+ if (st2xxx_uctr_mask() != 0)
+ {
+ save_item(NAME(m_uctr));
+ save_item(NAME(m_usr));
+ save_item(NAME(m_irctr));
+ save_item(NAME(m_bctr));
+ save_item(NAME(m_brs));
+ save_item(NAME(m_bdiv));
+ }
+}
+
+void st2xxx_device::device_reset()
+{
+ m6502_device::device_reset();
+
+ // reset port registers
+ std::fill(std::begin(m_pdata), std::end(m_pdata), 0xff);
+ std::fill(std::begin(m_pctrl), std::end(m_pctrl), 0);
+ std::fill(std::begin(m_psel), std::end(m_psel), 0xff);
+ std::fill(std::begin(m_pfun), std::end(m_pfun), 0);
+ for (auto &cb : m_out_port_cb)
+ cb(0xff);
+ m_pmcr = 0x80;
+
+ // reset bank registers
+ mi_st2xxx &m = downcast<mi_st2xxx &>(*mintf);
+ m.irr_enable = false;
+ m.irr = 0;
+ m.prr = 0;
+ m.drr = 0;
+
+ // reset interrupt registers
+ m_ireq = 0;
+ m_iena = 0;
+ update_irq_state();
+
+ // reset base timer
+ bten_w(0);
+ m_btsr = 0;
+
+ // reset prescaler
+ prs_w(0x80);
+
+ // reset miscellaneous registers
+ m_sys = 0;
+ m_misc = st2xxx_wdten_on_reset() ? 0x0c : 0;
+
+ // reset LCDC registers
+ m_lssa = 0;
+ m_lvpw = 0;
+ m_lxmax = 0;
+ m_lymax = 0;
+ m_lpan = 0;
+ m_lctr = 0x80;
+ m_lckr = 0;
+ m_lfra = 0;
+ m_lac = 0;
+ m_lpwm = 0;
+ m_lcd_timer->adjust(attotime::never);
+
+ // reset SPI
+ m_sctr = 0;
+ m_sckr = 0;
+ m_ssr = 0;
+ m_smod = 0;
+
+ // reset UART and BRG
+ m_uctr = 0;
+ m_usr = BIT(st2xxx_uctr_mask(), 4) ? 0x01 : 0;
+ m_irctr = 0;
+ m_bctr = 0;
+}
+
+u8 st2xxx_device::active_irq_level() const
+{
+ // IREQH interrupts have priority over IREQL interrupts
+ u16 ireq_active = swapendian_int16(m_ireq & m_iena);
+ if (ireq_active != 0)
+ return 31 - (8 ^ count_leading_zeros_32(ireq_active & -ireq_active));
+ else
+ return 0xff;
+}
+
+u8 st2xxx_device::read_vector(u16 adr)
+{
+ if (adr >= 0xfffe)
+ {
+ if (adr == 0xfffe)
+ {
+ set_irq_service(true);
+
+ // Make sure this doesn't change in between vector pull cycles
+ m_irq_level = irq_taken ? active_irq_level() : 0xff;
+ }
+
+ if (m_irq_level != 0xff)
+ {
+ adr -= (m_irq_level + 3) << 1;
+
+ LOGMASKED(LOG_IRQ, "Acknowledging %s interrupt (PC = $%04X, IREQ = $%04X, IENA = $%04X, vector pull from $%04X)\n",
+ st2xxx_irq_name(m_irq_level),
+ PPC,
+ m_ireq,
+ m_iena,
+ adr & 0x7fff);
+
+ if (BIT(adr, 0))
+ {
+ m_ireq &= ~(1 << m_irq_level);
+ update_irq_state();
+ }
+ }
+ }
+ return downcast<mi_st2xxx &>(*mintf).read_vector(adr);
+}
+
+u8 st2xxx_device::pdata_r(offs_t offset)
+{
+ u8 pdata = m_pdata[offset];
+ u8 pinmask = ~m_pctrl[offset] | (pdata & ~m_psel[offset]);
+ if (pinmask != 0)
+ pdata = (pdata & ~pinmask) | (m_in_port_cb[offset](0, pinmask) & pinmask);
+ return pdata;
+}
+
+void st2xxx_device::pdata_w(offs_t offset, u8 data)
+{
+ // Set output state (CMOS or open drain) or activate/deactive pullups for input pins
+ if (data != m_pdata[offset])
+ {
+ m_pdata[offset] = data;
+ m_out_port_cb[offset](0, data, m_pctrl[offset]);
+ }
+}
+
+u8 st2xxx_device::pctrl_r(offs_t offset)
+{
+ return m_pctrl[offset];
+}
+
+void st2xxx_device::pctrl_w(offs_t offset, u8 data)
+{
+ if (data != m_pctrl[offset])
+ {
+ m_pctrl[offset] = data;
+ m_out_port_cb[offset](0, m_pdata[offset], data);
+ }
+}
+
+u8 st2xxx_device::pfc_r()
+{
+ return m_pfun[0];
+}
+
+void st2xxx_device::pfc_w(u8 data)
+{
+ m_pfun[0] = data;
+}
+
+u8 st2xxx_device::pfd_r()
+{
+ return m_pfun[1];
+}
+
+void st2xxx_device::pfd_w(u8 data)
+{
+ m_pfun[1] = data;
+}
+
+u8 st2xxx_device::pl_r()
+{
+ return pdata_r(6);
+}
+
+void st2xxx_device::pl_w(u8 data)
+{
+ pdata_w(6, data);
+}
+
+u8 st2xxx_device::psc_r()
+{
+ return m_psel[2];
+}
+
+void st2xxx_device::psc_w(u8 data)
+{
+ m_psel[2] = data;
+}
+
+u8 st2xxx_device::pse_r()
+{
+ return m_psel[4];
+}
+
+void st2xxx_device::pse_w(u8 data)
+{
+ m_psel[4] = data;
+}
+
+u8 st2xxx_device::pcl_r()
+{
+ return pctrl_r(6);
+}
+
+void st2xxx_device::pcl_w(u8 data)
+{
+ pctrl_w(6, data);
+}
+
+u8 st2xxx_device::pmcr_r()
+{
+ return m_pmcr;
+}
+
+void st2xxx_device::pmcr_w(u8 data)
+{
+ m_pmcr = data & st2xxx_pmcr_mask();
+}
+
+u8 st2xxx_device::bten_r()
+{
+ return m_bten;
+}
+
+void st2xxx_device::bten_w(u8 data)
+{
+ data &= m_bt_mask;
+
+ for (int n = 0; n < 8; n++)
+ {
+ if (BIT(data, n) && !BIT(m_bten, n))
+ {
+ unsigned div = st2xxx_bt_divider(n);
+ assert(div != 0);
+ assert(m_base_timer[n] != nullptr);
+ m_base_timer[n]->adjust(attotime::from_ticks(div, 32768), n);
+ LOGMASKED(LOG_BT, "Base timer %d enabled at %.1f Hz (PC = $%04X)\n", n, 32768.0 / div, PPC);
+ }
+ else if (!BIT(data, n) && BIT(m_bten, n))
+ {
+ m_base_timer[n]->adjust(attotime::never);
+ LOGMASKED(LOG_BT, "Base timer %d disabled (PC = $%04X)\n", n, PPC);
+ }
+ }
+
+ m_bten = data;
+}
+
+u8 st2xxx_device::btsr_r()
+{
+ return m_btsr;
+}
+
+void st2xxx_device::btclr_w(u8 data)
+{
+ // Write 1 to clear each individual bit
+ m_btsr &= ~data;
+}
+
+void st2xxx_device::btclr_all_w(u8 data)
+{
+ // Only bit 7 has any effect
+ if (BIT(data, 7))
+ m_btsr = 0;
+}
+
+u16 st2xxx_device::pres_count() const
+{
+ return (m_pres_base + ((m_prs & 0x60) == 0x40 ? attotime_to_cycles(machine().time() - m_pres_started) : 0));
+}
+
+u8 st2xxx_device::prs_r()
+{
+ return pres_count() & 0xff;
+}
+
+void st2xxx_device::prs_w(u8 data)
+{
+ data &= st2xxx_prs_mask();
+
+ // Bit 7 produces prescaler reset pulse
+ if (BIT(data, 7))
+ {
+ st2xxx_tclk_stop();
+ m_pres_base = 0;
+ if ((m_prs & 0x60) == 0x40)
+ {
+ m_pres_started = machine().time();
+ st2xxx_tclk_start();
+ }
+ data &= 0x7f;
+ }
+
+ // Bit 6 enables prescaler; bit 5 selects clock source
+ if ((data & 0x60) == 0x40 && (m_prs & 0x60) != 0x40)
+ {
+ m_pres_started = machine().time();
+ st2xxx_tclk_start();
+ }
+ else if ((data & 0x60) == 0x40 && (m_prs & 0x60) != 0x40)
+ {
+ st2xxx_tclk_stop();
+ m_pres_base += attotime_to_cycles(machine().time() - m_pres_started);
+ }
+
+ m_prs = data;
+}
+
+u8 st2xxx_device::sys_r()
+{
+ return m_sys | 0x01;
+}
+
+void st2xxx_device::sys_w(u8 data)
+{
+ u8 mask = st2xxx_sys_mask();
+ m_sys = data & mask;
+ if (BIT(mask, 1))
+ downcast<mi_st2xxx &>(*mintf).irr_enable = BIT(data, 1);
+}
+
+u8 st2xxx_device::misc_r()
+{
+ return m_misc;
+}
+
+void st2xxx_device::misc_w(u8 data)
+{
+ m_misc = data & st2xxx_misc_mask();
+}
+
+u8 st2xxx_device::irrl_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).irr & 0xff;
+}
+
+void st2xxx_device::irrl_w(u8 data)
+{
+ u16 &irr = downcast<mi_st2xxx &>(*mintf).irr;
+ irr = (data & m_prr_mask) | (irr & 0xff00);
+}
+
+u8 st2xxx_device::irrh_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).irr >> 8;
+}
+
+void st2xxx_device::irrh_w(u8 data)
+{
+ u16 &irr = downcast<mi_st2xxx &>(*mintf).irr;
+ irr = ((u16(data) << 8) & m_prr_mask) | (irr & 0x00ff);
+}
+
+u8 st2xxx_device::prrl_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).prr & 0xff;
+}
+
+void st2xxx_device::prrl_w(u8 data)
+{
+ u16 &prr = downcast<mi_st2xxx &>(*mintf).prr;
+ prr = (data & m_prr_mask) | (prr & 0xff00);
+}
+
+u8 st2xxx_device::prrh_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).prr >> 8;
+}
+
+void st2xxx_device::prrh_w(u8 data)
+{
+ u16 &prr = downcast<mi_st2xxx &>(*mintf).prr;
+ prr = ((u16(data) << 8) & m_prr_mask) | (prr & 0x00ff);
+}
+
+u8 st2xxx_device::drrl_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).drr & 0xff;
+}
+
+void st2xxx_device::drrl_w(u8 data)
+{
+ u16 &drr = downcast<mi_st2xxx &>(*mintf).drr;
+ drr = (data & m_drr_mask) | (drr & 0xff00);
+}
+
+u8 st2xxx_device::drrh_r()
+{
+ return downcast<mi_st2xxx &>(*mintf).drr >> 8;
+}
+
+void st2xxx_device::drrh_w(u8 data)
+{
+ u16 &drr = downcast<mi_st2xxx &>(*mintf).drr;
+ drr = ((u16(data) << 8) & m_drr_mask) | (drr & 0x00ff);
+}
+
+u8 st2xxx_device::ireql_r()
+{
+ return m_ireq & 0x00ff;
+}
+
+void st2xxx_device::ireql_w(u8 data)
+{
+ if ((m_ireq & ~data & 0x00ff) != 0)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ if (!BIT(data, i) && BIT(m_ireq, i))
+ LOGMASKED(LOG_IRQ, "%s interrupt cleared (PC = $%04X)\n", st2xxx_irq_name(i), PPC);
+ }
+ m_ireq &= data | 0xff00;
+ update_irq_state();
+ }
+}
+
+u8 st2xxx_device::ireqh_r()
+{
+ return m_ireq >> 8;
+}
+
+void st2xxx_device::ireqh_w(u8 data)
+{
+ if ((m_ireq & ~(u16(data) << 8) & 0xff00) != 0)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ if (!BIT(data, i) && BIT(m_ireq, i + 8))
+ LOGMASKED(LOG_IRQ, "%s interrupt cleared (PC = $%04X)\n", st2xxx_irq_name(i + 8), PPC);
+ }
+ m_ireq &= u16(data) << 8 | 0x00ff;
+ update_irq_state();
+ }
+}
+
+u8 st2xxx_device::ienal_r()
+{
+ return m_iena & 0x00ff;
+}
+
+void st2xxx_device::ienal_w(u8 data)
+{
+ data &= st2xxx_ireq_mask();
+ if (data != (m_iena & 0x00ff))
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ if (BIT(data, i) != BIT(m_iena, i))
+ LOGMASKED(LOG_IRQ, "%s interrupt %sabled (PC = $%04X)\n",
+ st2xxx_irq_name(i),
+ BIT(data, i) ? "en" : "dis",
+ PPC);
+ }
+ m_iena = (m_iena & 0xff00) | data;
+ update_irq_state();
+ }
+}
+
+u8 st2xxx_device::ienah_r()
+{
+ return m_iena >> 8;
+}
+
+void st2xxx_device::ienah_w(u8 data)
+{
+ data &= st2xxx_ireq_mask() >> 8;
+ if (data != (m_iena >> 8))
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ if (BIT(data, i) != BIT(m_iena, i + 8))
+ LOGMASKED(LOG_IRQ, "%s interrupt %sabled (PC = $%04X)\n",
+ st2xxx_irq_name(i + 8),
+ BIT(data, i) ? "en" : "dis",
+ PPC);
+ }
+ m_iena = (m_iena & 0x00ff) | (u16(data) << 8);
+ update_irq_state();
+ }
+}
+
+void st2xxx_device::lssal_w(u8 data)
+{
+ m_lssa = (m_lssa & 0xff00) | data;
+}
+
+void st2xxx_device::lssah_w(u8 data)
+{
+ m_lssa = (m_lssa & 0x00ff) | (u16(data) << 8);
+}
+
+void st2xxx_device::lvpw_w(u8 data)
+{
+ m_lvpw = data;
+}
+
+u8 st2xxx_device::lxmax_r()
+{
+ return m_lxmax;
+}
+
+void st2xxx_device::lxmax_w(u8 data)
+{
+ m_lxmax = data;
+ lfr_recalculate_period();
+}
+
+u8 st2xxx_device::lymax_r()
+{
+ return m_lymax;
+}
+
+void st2xxx_device::lymax_w(u8 data)
+{
+ m_lymax = data;
+ lfr_recalculate_period();
+}
+
+u8 st2xxx_device::lpan_r()
+{
+ return m_lpan;
+}
+
+void st2xxx_device::lpan_w(u8 data)
+{
+ m_lpan = data & st2xxx_lpan_mask();
+}
+
+u8 st2xxx_device::lctr_r()
+{
+ return m_lctr;
+}
+
+void st2xxx_device::lctr_w(u8 data)
+{
+ data &= st2xxx_lctr_mask();
+ u8 old_lctr = std::exchange(m_lctr, data);
+
+ if ((old_lctr & 0xbf) != (m_lctr & 0xbf))
+ lfr_recalculate_period();
+}
+
+void st2xxx_device::lckr_w(u8 data)
+{
+ m_lckr = data & st2xxx_lckr_mask();
+ lfr_recalculate_period();
+}
+
+void st2xxx_device::lfra_w(u8 data)
+{
+ m_lfra = data & 0x3f;
+ lfr_recalculate_period();
+}
+
+void st2xxx_device::lfr_recalculate_period()
+{
+ if (!BIT(m_lctr, 7))
+ {
+ unsigned clocks = st2xxx_lfr_clocks();
+ assert(clocks != 0);
+ attotime period = cycles_to_attotime(clocks);
+ LOGMASKED(LOG_LCDC, "LCD frame rate = %f Hz (PC = $%04X)\n", period.as_hz(), PPC);
+ m_lcd_timer->adjust(period, 0, period);
+ }
+ else
+ m_lcd_timer->adjust(attotime::never);
+}
+
+u8 st2xxx_device::lac_r()
+{
+ return m_lac | 0xe0;
+}
+
+void st2xxx_device::lac_w(u8 data)
+{
+ m_lac = data & 0x1f;
+}
+
+u8 st2xxx_device::lpwm_r()
+{
+ return m_lpwm | ~st2xxx_lpwm_mask();
+}
+
+void st2xxx_device::lpwm_w(u8 data)
+{
+ m_lpwm = data & st2xxx_lpwm_mask();
+}
+
+u8 st2xxx_device::sctr_r()
+{
+ return m_sctr;
+}
+
+void st2xxx_device::sctr_w(u8 data)
+{
+ // TXEMP on wakeup?
+ if (!BIT(m_sctr, 7) && BIT(data, 7))
+ m_ssr |= 0x20;
+
+ m_sctr = data;
+}
+
+u8 st2xxx_device::sckr_r()
+{
+ return m_sckr | 0x80;
+}
+
+void st2xxx_device::sckr_w(u8 data)
+{
+ m_sckr = data & 0x7f;
+}
+
+u8 st2xxx_device::ssr_r()
+{
+ return m_ssr | 0x88;
+}
+
+void st2xxx_device::ssr_w(u8 data)
+{
+ // Write any value to clear
+ m_ssr = 0;
+}
+
+u8 st2xxx_device::smod_r()
+{
+ return m_smod | 0xf0;
+}
+
+void st2xxx_device::smod_w(u8 data)
+{
+ m_smod = data & 0x0f;
+}
+
+u8 st2xxx_device::uctr_r()
+{
+ return m_uctr | ~st2xxx_uctr_mask();
+}
+
+void st2xxx_device::uctr_w(u8 data)
+{
+ m_uctr = data & st2xxx_uctr_mask();
+}
+
+u8 st2xxx_device::usr_r()
+{
+ return m_usr | 0x80;
+}
+
+void st2xxx_device::ustr_trg_w(u8 data)
+{
+ m_usr = (m_usr & 0x7a) | (data & 0x05);
+}
+
+void st2xxx_device::usr_clr_w(u8 data)
+{
+ m_usr &= ~data;
+}
+
+u8 st2xxx_device::irctr_r()
+{
+ return m_irctr | 0x3c;
+}
+
+void st2xxx_device::irctr_w(u8 data)
+{
+ m_irctr = data & 0xc7;
+}
+
+u8 st2xxx_device::udata_r()
+{
+ return 0;
+}
+
+void st2xxx_device::udata_w(u8 data)
+{
+ logerror("Writing %02X to UART transmitter (PC = %04X)\n", data, PPC);
+}
+
+u8 st2xxx_device::bctr_r()
+{
+ return m_bctr | ~st2xxx_bctr_mask();
+}
+
+void st2xxx_device::bctr_w(u8 data)
+{
+ m_bctr = data & st2xxx_bctr_mask();
+}
+
+u8 st2xxx_device::brs_r()
+{
+ return m_brs;
+}
+
+void st2xxx_device::brs_w(u8 data)
+{
+ m_brs = data;
+}
+
+u8 st2xxx_device::bdiv_r()
+{
+ return m_bdiv;
+}
+
+void st2xxx_device::bdiv_w(u8 data)
+{
+ m_bdiv = data;
+}
diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h
new file mode 100644
index 00000000000..5189cb24a5d
--- /dev/null
+++ b/src/devices/cpu/m6502/st2xxx.h
@@ -0,0 +1,299 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_M6502_ST2XXX_H
+#define MAME_CPU_M6502_ST2XXX_H
+
+#pragma once
+
+#include "w65c02s.h"
+
+class st2xxx_device : public w65c02s_device {
+public:
+ enum {
+ ST_PAOUT = M6502_IR + 1,
+ ST_PBOUT,
+ ST_PCOUT,
+ ST_PDOUT,
+ ST_PEOUT,
+ ST_PFOUT,
+ ST_PLOUT,
+ ST_PCA,
+ ST_PCB,
+ ST_PCC,
+ ST_PCD,
+ ST_PCE,
+ ST_PCF,
+ ST_PCL,
+ ST_PSA,
+ ST_PSB,
+ ST_PSC,
+ ST_PSD,
+ ST_PSE,
+ ST_PSF,
+ ST_PSL,
+ ST_PFC,
+ ST_PFD,
+ ST_PMCR,
+ ST_PSGC,
+ ST_BTEN,
+ ST_BTSR,
+ ST_PRS,
+ ST_SYS,
+ ST_IRR,
+ ST_PRR,
+ ST_DRR,
+ ST_DMR,
+ ST_MISC,
+ ST_IREQ,
+ ST_IENA,
+ ST_LSSA,
+ ST_LVPW,
+ ST_LXMAX,
+ ST_LYMAX,
+ ST_LPAN,
+ ST_LCTR,
+ ST_LCKR,
+ ST_LFRA,
+ ST_LAC,
+ ST_LPWM,
+ ST_SCTR,
+ ST_SCKR,
+ ST_SSR,
+ ST_SMOD,
+ ST_UCTR,
+ ST_USR,
+ ST_IRCTR,
+ ST_BCTR,
+ ST_BRS,
+ ST_BDIV
+ };
+
+ auto in_pa_callback() { return m_in_port_cb[0].bind(); }
+ auto out_pa_callback() { return m_out_port_cb[0].bind(); }
+ auto in_pb_callback() { return m_in_port_cb[1].bind(); }
+ auto out_pb_callback() { return m_out_port_cb[1].bind(); }
+ auto in_pc_callback() { return m_in_port_cb[2].bind(); }
+ auto out_pc_callback() { return m_out_port_cb[2].bind(); }
+ auto in_pd_callback() { return m_in_port_cb[3].bind(); }
+ auto out_pd_callback() { return m_out_port_cb[3].bind(); }
+ auto in_pe_callback() { return m_in_port_cb[4].bind(); }
+ auto out_pe_callback() { return m_out_port_cb[4].bind(); }
+ auto in_pf_callback() { return m_in_port_cb[5].bind(); }
+ auto out_pf_callback() { return m_out_port_cb[5].bind(); }
+ auto in_pl_callback() { return m_in_port_cb[6].bind(); }
+ auto out_pl_callback() { return m_out_port_cb[6].bind(); }
+
+protected:
+ st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram);
+
+ virtual space_config_vector memory_space_config() const override;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u16 st2xxx_ireq_mask() const = 0;
+ virtual const char *st2xxx_irq_name(int i) const = 0;
+ virtual u8 st2xxx_pmcr_mask() const = 0;
+ virtual unsigned st2xxx_bt_divider(int n) const = 0;
+ virtual u8 st2xxx_prs_mask() const = 0;
+ virtual void st2xxx_tclk_start() { }
+ virtual void st2xxx_tclk_stop() { }
+ virtual u8 st2xxx_sys_mask() const = 0;
+ virtual u8 st2xxx_misc_mask() const = 0;
+ virtual bool st2xxx_wdten_on_reset() const { return false; }
+ virtual bool st2xxx_has_dma() const { return false; }
+ virtual u8 st2xxx_lpan_mask() const = 0;
+ virtual u8 st2xxx_lctr_mask() const = 0;
+ virtual u8 st2xxx_lckr_mask() const = 0;
+ virtual u8 st2xxx_lpwm_mask() const = 0;
+ virtual unsigned st2xxx_lfr_clocks() const = 0;
+ virtual bool st2xxx_has_spi() const = 0;
+ virtual bool st2xxx_spi_iis() const { return false; }
+ virtual u8 st2xxx_uctr_mask() const = 0;
+ virtual u8 st2xxx_bctr_mask() const = 0;
+
+ class mi_st2xxx : public memory_interface {
+ public:
+ virtual u8 read_vector(u16 adr) = 0;
+
+ memory_access<26, 0, 0, ENDIANNESS_LITTLE>::cache dcache;
+ memory_access<26, 0, 0, ENDIANNESS_LITTLE>::specific data;
+
+ bool irq_service;
+ bool irr_enable;
+ u16 irr;
+ u16 prr;
+ u16 drr;
+ };
+
+ void init_base_timer(u16 ireq);
+ void init_lcd_timer(u16 ireq);
+ void save_common_registers();
+
+ virtual u8 read_vector(u16 adr) override;
+ virtual void end_interrupt() override { set_irq_service(false); }
+
+ void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; }
+ void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; }
+ u8 active_irq_level() const;
+
+ TIMER_CALLBACK_MEMBER(bt_interrupt);
+ TIMER_CALLBACK_MEMBER(lcd_interrupt);
+
+ u8 pdata_r(offs_t offset);
+ void pdata_w(offs_t offset, u8 data);
+ u8 pctrl_r(offs_t offset);
+ void pctrl_w(offs_t offset, u8 data);
+ u8 pl_r();
+ void pl_w(u8 data);
+ u8 pcl_r();
+ void pcl_w(u8 data);
+ u8 psc_r();
+ void psc_w(u8 data);
+ u8 pse_r();
+ void pse_w(u8 data);
+ u8 pfc_r();
+ void pfc_w(u8 data);
+ u8 pfd_r();
+ void pfd_w(u8 data);
+ u8 pmcr_r();
+ void pmcr_w(u8 data);
+
+ u8 sys_r();
+ void sys_w(u8 data);
+ u8 misc_r();
+ void misc_w(u8 data);
+
+ u8 irrl_r();
+ void irrl_w(u8 data);
+ u8 irrh_r();
+ void irrh_w(u8 data);
+ u8 prrl_r();
+ void prrl_w(u8 data);
+ u8 prrh_r();
+ void prrh_w(u8 data);
+ u8 drrl_r();
+ void drrl_w(u8 data);
+ u8 drrh_r();
+ void drrh_w(u8 data);
+
+ u8 bten_r();
+ void bten_w(u8 data);
+ u8 btsr_r();
+ void btclr_w(u8 data);
+ void btclr_all_w(u8 data);
+
+ u16 pres_count() const;
+ u8 prs_r();
+ void prs_w(u8 data);
+
+ u8 ireql_r();
+ void ireql_w(u8 data);
+ u8 ireqh_r();
+ void ireqh_w(u8 data);
+ u8 ienal_r();
+ void ienal_w(u8 data);
+ u8 ienah_r();
+ void ienah_w(u8 data);
+
+ void lssal_w(u8 data);
+ void lssah_w(u8 data);
+ void lvpw_w(u8 data);
+ u8 lxmax_r();
+ void lxmax_w(u8 data);
+ u8 lymax_r();
+ void lymax_w(u8 data);
+ u8 lpan_r();
+ void lpan_w(u8 data);
+ u8 lctr_r();
+ void lctr_w(u8 data);
+ void lckr_w(u8 data);
+ void lfra_w(u8 data);
+ void lfr_recalculate_period();
+ u8 lac_r();
+ void lac_w(u8 data);
+ u8 lpwm_r();
+ void lpwm_w(u8 data);
+
+ u8 sctr_r();
+ void sctr_w(u8 data);
+ u8 sckr_r();
+ void sckr_w(u8 data);
+ u8 ssr_r();
+ void ssr_w(u8 data);
+ u8 smod_r();
+ void smod_w(u8 data);
+
+ u8 uctr_r();
+ void uctr_w(u8 data);
+ u8 usr_r();
+ void ustr_trg_w(u8 data);
+ void usr_clr_w(u8 data);
+ u8 irctr_r();
+ void irctr_w(u8 data);
+ u8 udata_r();
+ void udata_w(u8 data);
+ u8 bctr_r();
+ void bctr_w(u8 data);
+ u8 brs_r();
+ void brs_w(u8 data);
+ u8 bdiv_r();
+ void bdiv_w(u8 data);
+
+ address_space_config m_data_config;
+
+ devcb_read8::array<7> m_in_port_cb;
+ devcb_write8::array<7> m_out_port_cb;
+
+ const u16 m_prr_mask;
+ const u16 m_drr_mask;
+
+ u8 m_pdata[7];
+ u8 m_pctrl[7];
+ u8 m_psel[7];
+ u8 m_pfun[2];
+ u8 m_pmcr;
+
+ u8 m_bten;
+ u8 m_btsr;
+ emu_timer *m_base_timer[8];
+ u8 m_bt_mask;
+ u16 m_bt_ireq;
+
+ u16 m_pres_base;
+ attotime m_pres_started;
+ u8 m_prs;
+
+ u8 m_sys;
+ u8 m_misc;
+
+ u16 m_ireq;
+ u16 m_iena;
+ u8 m_irq_level;
+
+ u16 m_lssa;
+ u8 m_lvpw;
+ u8 m_lxmax;
+ u8 m_lymax;
+ u8 m_lpan;
+ u8 m_lctr;
+ u8 m_lckr;
+ u8 m_lfra;
+ u8 m_lac;
+ u8 m_lpwm;
+ u16 m_lcd_ireq;
+ emu_timer *m_lcd_timer;
+
+ u8 m_sctr;
+ u8 m_sckr;
+ u8 m_ssr;
+ u8 m_smod;
+
+ u8 m_uctr;
+ u8 m_usr;
+ u8 m_irctr;
+ u8 m_bctr;
+ u8 m_brs;
+ u8 m_bdiv;
+};
+
+#endif // MAME_CPU_M6502_ST2XXX_H
diff --git a/src/devices/cpu/m6502/w65c02.cpp b/src/devices/cpu/m6502/w65c02.cpp
new file mode 100644
index 00000000000..c482b31d449
--- /dev/null
+++ b/src/devices/cpu/m6502/w65c02.cpp
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ w65c02.cpp
+
+ WDC W65C02, CMOS variant with some additional instructions
+ (but not the bitwise ones)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "w65c02.h"
+#include "w65c02d.h"
+
+DEFINE_DEVICE_TYPE(W65C02, w65c02_device, "w65c02", "WDC W65C02")
+
+w65c02_device::w65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, W65C02, tag, owner, clock)
+{
+}
+
+w65c02_device::w65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, type, tag, owner, clock)
+{
+}
+
+std::unique_ptr<util::disasm_interface> w65c02_device::create_disassembler()
+{
+ return std::make_unique<w65c02_disassembler>();
+}
+
+#include "cpu/m6502/w65c02.hxx"
diff --git a/src/devices/cpu/m6502/m65c02.h b/src/devices/cpu/m6502/w65c02.h
index e61161cc9dd..552565d4203 100644
--- a/src/devices/cpu/m6502/m65c02.h
+++ b/src/devices/cpu/m6502/w65c02.h
@@ -2,29 +2,29 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m65c02.h
+ w65c02.h
- MOS Technology 6502, CMOS variant with some additional instructions
+ WDC W65C02, CMOS variant with some additional instructions
(but not the bitwise ones)
***************************************************************************/
-#ifndef MAME_CPU_M6502_M65C02_H
-#define MAME_CPU_M6502_M65C02_H
+#ifndef MAME_CPU_M6502_W65C02_H
+#define MAME_CPU_M6502_W65C02_H
#pragma once
#include "m6502.h"
-class m65c02_device : public m6502_device {
+class w65c02_device : public m6502_device {
public:
- m65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ w65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void do_exec_full() override;
virtual void do_exec_partial() override;
protected:
- m65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ w65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
#define O(o) void o ## _full(); void o ## _partial()
@@ -67,11 +67,11 @@ protected:
};
enum {
- M65C02_IRQ_LINE = m6502_device::IRQ_LINE,
- M65C02_NMI_LINE = m6502_device::NMI_LINE,
- M65C02_SET_OVERFLOW = m6502_device::V_LINE
+ W65C02_IRQ_LINE = m6502_device::IRQ_LINE,
+ W65C02_NMI_LINE = m6502_device::NMI_LINE,
+ W65C02_SET_OVERFLOW = m6502_device::V_LINE
};
-DECLARE_DEVICE_TYPE(M65C02, m65c02_device)
+DECLARE_DEVICE_TYPE(W65C02, w65c02_device)
-#endif // MAME_CPU_M6502_M65C02_H
+#endif // MAME_CPU_M6502_W65C02_H
diff --git a/src/devices/cpu/m6502/m65c02d.cpp b/src/devices/cpu/m6502/w65c02d.cpp
index 2c7b3b81fc3..919d2ddf6f5 100644
--- a/src/devices/cpu/m6502/m65c02d.cpp
+++ b/src/devices/cpu/m6502/w65c02d.cpp
@@ -2,17 +2,17 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m65c02d.cpp
+ w65c02d.cpp
- MOS Technology 6502, CMOS variant with some additional instructions
+ WDC W65C02, CMOS variant with some additional instructions
(but not the bitwise ones), disassembler
***************************************************************************/
#include "emu.h"
-#include "m65c02d.h"
-#include "cpu/m6502/m65c02d.hxx"
+#include "w65c02d.h"
+#include "cpu/m6502/w65c02d.hxx"
-m65c02_disassembler::m65c02_disassembler() : m6502_base_disassembler(disasm_entries)
+w65c02_disassembler::w65c02_disassembler() : m6502_base_disassembler(disasm_entries)
{
}
diff --git a/src/devices/cpu/m6502/m65c02d.h b/src/devices/cpu/m6502/w65c02d.h
index 77b134c4b95..1e9edec6a14 100644
--- a/src/devices/cpu/m6502/m65c02d.h
+++ b/src/devices/cpu/m6502/w65c02d.h
@@ -2,25 +2,25 @@
// copyright-holders:Olivier Galibert
/***************************************************************************
- m65c02d.h
+ w65c02d.h
- MOS Technology 6502, CMOS variant with some additional instructions
+ WDC W65C02, CMOS variant with some additional instructions
(but not the bitwise ones), disassembler
***************************************************************************/
-#ifndef MAME_CPU_M6502_M65C02D_H
-#define MAME_CPU_M6502_M65C02D_H
+#ifndef MAME_CPU_M6502_W65C02D_H
+#define MAME_CPU_M6502_W65C02D_H
#pragma once
#include "m6502d.h"
-class m65c02_disassembler : public m6502_base_disassembler
+class w65c02_disassembler : public m6502_base_disassembler
{
public:
- m65c02_disassembler();
- virtual ~m65c02_disassembler() = default;
+ w65c02_disassembler();
+ virtual ~w65c02_disassembler() = default;
private:
static const disasm_entry disasm_entries[0x100];
diff --git a/src/devices/cpu/m6502/w65c02s.cpp b/src/devices/cpu/m6502/w65c02s.cpp
new file mode 100644
index 00000000000..17c61bafc4e
--- /dev/null
+++ b/src/devices/cpu/m6502/w65c02s.cpp
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ w65c02s.cpp
+
+ WDC W65C02S, CMOS variant with bitwise instructions, BE, ML, VP pins
+ and cleaner fetch patterns
+
+***************************************************************************/
+
+#include "emu.h"
+#include "w65c02s.h"
+#include "r65c02d.h"
+
+DEFINE_DEVICE_TYPE(W65C02S, w65c02s_device, "w65c02s", "WDC W65C02S")
+
+w65c02s_device::w65c02s_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ w65c02s_device(mconfig, W65C02S, tag, owner, clock)
+{
+}
+
+w65c02s_device::w65c02s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ w65c02_device(mconfig, type, tag, owner, clock)
+{
+}
+
+std::unique_ptr<util::disasm_interface> w65c02s_device::create_disassembler()
+{
+ return std::make_unique<r65c02_disassembler>();
+}
+
+#include "cpu/m6502/w65c02s.hxx"
diff --git a/src/devices/cpu/m6502/w65c02s.h b/src/devices/cpu/m6502/w65c02s.h
new file mode 100644
index 00000000000..7a3da04bcd5
--- /dev/null
+++ b/src/devices/cpu/m6502/w65c02s.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ w65c02s.h
+
+ WDC W65C02S, CMOS variant with bitwise instructions, BE, ML, VP pins
+ and cleaner fetch patterns
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_W65C02S_H
+#define MAME_CPU_M6502_W65C02S_H
+
+#include "w65c02.h"
+
+class w65c02s_device : public w65c02_device {
+public:
+ w65c02s_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+ virtual void do_exec_full() override;
+ virtual void do_exec_partial() override;
+
+protected:
+ w65c02s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual uint8_t read_vector(uint16_t adr) { return mintf->read_arg(adr); }
+ virtual void end_interrupt() { }
+
+#define O(o) void o ## _full(); void o ## _partial()
+
+ O(adc_s_abx); O(adc_s_aby); O(adc_s_idx); O(adc_s_idy); O(adc_s_zpx);
+ O(and_s_abx); O(and_s_aby); O(and_s_idx); O(and_s_idy); O(and_s_zpx);
+ O(asl_s_abx); O(asl_s_zpg); O(asl_s_zpx);
+ O(bit_s_abx); O(bit_s_zpx);
+ O(brk_s_imp);
+ O(cmp_s_abx); O(cmp_s_aby); O(cmp_s_idx); O(cmp_s_idy); O(cmp_s_zpx);
+ O(dec_s_abx); O(dec_s_zpg); O(dec_s_zpx);
+ O(eor_s_abx); O(eor_s_aby); O(eor_s_idx); O(eor_s_idy); O(eor_s_zpx);
+ O(inc_s_abx); O(inc_s_zpg); O(inc_s_zpx);
+ O(jmp_s_iax); O(jmp_s_ind);
+ O(lda_s_abx); O(lda_s_aby); O(lda_s_idx); O(lda_s_idy); O(lda_s_zpx);
+ O(ldx_s_aby); O(ldx_s_zpy);
+ O(ldy_s_abx); O(ldy_s_zpx);
+ O(lsr_s_abx); O(lsr_s_zpg); O(lsr_s_zpx);
+ O(nop_s_abx); O(nop_s_zpx);
+ O(ora_s_abx); O(ora_s_aby); O(ora_s_idx); O(ora_s_idy); O(ora_s_zpx);
+ O(pla_s_imp);
+ O(plp_s_imp);
+ O(plx_s_imp);
+ O(ply_s_imp);
+ O(rol_s_abx); O(rol_s_zpg); O(rol_s_zpx);
+ O(ror_s_abx); O(ror_s_zpg); O(ror_s_zpx);
+ O(rti_s_imp);
+ O(rts_s_imp);
+ O(sbc_s_abx); O(sbc_s_aby); O(sbc_s_idx); O(sbc_s_idy); O(sbc_s_zpx);
+ O(sta_s_abx); O(sta_s_aby); O(sta_s_idx); O(sta_s_idy); O(sta_s_zpx);
+ O(stx_s_zpy);
+ O(sty_s_zpx);
+ O(stz_s_abx); O(stz_s_zpx);
+ O(trb_s_zpg);
+ O(tsb_s_zpg);
+ O(reset_s);
+
+#undef O
+};
+
+DECLARE_DEVICE_TYPE(W65C02S, w65c02s_device)
+
+#endif // MAME_CPU_M6502_W65C02S_H
diff --git a/src/devices/cpu/m6502/xavix.cpp b/src/devices/cpu/m6502/xavix.cpp
index 522d9374b5f..bf5eb25b925 100644
--- a/src/devices/cpu/m6502/xavix.cpp
+++ b/src/devices/cpu/m6502/xavix.cpp
@@ -34,28 +34,16 @@
DEFINE_DEVICE_TYPE(XAVIX, xavix_device, "xavix", "XaviX (SSD 97 / SSD 98)")
xavix_device::xavix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- m6502_device(mconfig, XAVIX, tag, owner, clock),
- XPC(0),
- m_lowbus_config("lowbus", ENDIANNESS_LITTLE, 8, 15),
- m_extbus_config("extbus", ENDIANNESS_LITTLE, 8, 24)
+ xavix_device(mconfig, XAVIX, tag, owner, clock)
{
- program_config.m_addr_width = 24;
- program_config.m_logaddr_width = 24;
- sprogram_config.m_addr_width = 24;
- sprogram_config.m_logaddr_width = 24;
- // XaviX specific spaces
- m_lowbus_config.m_addr_width = 15;
- m_lowbus_config.m_logaddr_width = 15;
- m_extbus_config.m_addr_width = 24;
- m_extbus_config.m_logaddr_width = 24;
-
}
xavix_device::xavix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, type, tag, owner, clock),
XPC(0),
m_lowbus_config("lowbus", ENDIANNESS_LITTLE, 8, 15),
- m_extbus_config("extbus", ENDIANNESS_LITTLE, 8, 24)
+ m_extbus_config("extbus", ENDIANNESS_LITTLE, 8, 24),
+ m_vector_callback(*this)
{
program_config.m_addr_width = 24;
program_config.m_logaddr_width = 24;
@@ -83,13 +71,10 @@ offs_t xavix_device::pc_to_external(u16 pc)
void xavix_device::device_start()
{
- if(cache_disabled)
- mintf = std::make_unique<mi_xavix_nd>(this);
- else
- mintf = std::make_unique<mi_xavix_normal>(this);
+ mintf = std::make_unique<mi_xavix>(this);
// bind delegates
- m_vector_callback.bind_relative_to(*owner());
+ m_vector_callback.resolve();
init();
@@ -116,29 +101,57 @@ void xavix_device::device_reset()
-xavix_device::mi_xavix_normal::mi_xavix_normal(xavix_device *_base)
+xavix_device::mi_xavix::mi_xavix(xavix_device *_base)
{
base = _base;
}
-void xavix_device::write_special_stack(uint8_t data)
+void xavix_device::write_special_stack(uint32_t addr, uint8_t data)
{
- m_special_stack[m_special_stackpos&0xff] = data;
+ if (m_use_private_stack_for_extra_callf_byte)
+ {
+ m_special_stack[m_special_stackpos & 0xff] = data;
+ }
+ else
+ {
+ write_stack(addr, data);
+ }
}
void xavix_device::dec_special_stack()
{
- m_special_stackpos--;
+ if (m_use_private_stack_for_extra_callf_byte)
+ {
+ m_special_stackpos--;
+ }
+ else
+ {
+ dec_SP();
+ }
}
void xavix_device::inc_special_stack()
{
- m_special_stackpos++;
+ if (m_use_private_stack_for_extra_callf_byte)
+ {
+ m_special_stackpos++;
+ }
+ else
+ {
+ inc_SP();
+ }
}
-uint8_t xavix_device::read_special_stack()
+uint8_t xavix_device::read_special_stack(uint32_t addr)
{
- return m_special_stack[m_special_stackpos&0xff];
+ if (m_use_private_stack_for_extra_callf_byte)
+ {
+ return m_special_stack[m_special_stackpos & 0xff];
+ }
+ else
+ {
+ return read_stack(addr);
+ }
}
@@ -167,32 +180,32 @@ inline uint8_t xavix_device::read_full_data(uint8_t databank, uint16_t adr)
}
else
{
- return m_extbus_space->read_byte((databank << 16) | adr);
+ return m_extbus_space->read_byte(((databank << 16) | adr) & 0x7fffff );
}
}
else
{
- return m_extbus_space->read_byte((databank << 16) | adr);
+ return m_extbus_space->read_byte(((databank << 16) | adr) & 0x7fffff );
}
}
// data reads
-inline uint8_t xavix_device::mi_xavix_normal::read(uint16_t adr)
+inline uint8_t xavix_device::mi_xavix::read(uint16_t adr)
{
uint8_t databank = base->get_databank();
return base->read_full_data(databank, adr);
}
// opcode reads
-uint8_t xavix_device::mi_xavix_normal::read_sync(uint16_t adr)
+uint8_t xavix_device::mi_xavix::read_sync(uint16_t adr)
{
- return scache->read_byte(base->adr_with_codebank(adr));
+ return csprogram.read_byte(base->adr_with_codebank(adr));
}
// oprand reads
-uint8_t xavix_device::mi_xavix_normal::read_arg(uint16_t adr)
+uint8_t xavix_device::mi_xavix::read_arg(uint16_t adr)
{
- return cache->read_byte(base->adr_with_codebank(adr));
+ return cprogram.read_byte(base->adr_with_codebank(adr));
}
// data writes
@@ -272,35 +285,21 @@ inline void xavix_device::write_full_data(uint8_t databank, uint16_t adr, uint8_
}
else
{
- m_extbus_space->write_byte((databank << 16) | adr, val);
+ m_extbus_space->write_byte(((databank << 16) | adr) & 0x7fffff, val);
}
}
else
{
- m_extbus_space->write_byte((databank << 16) | adr, val);
+ m_extbus_space->write_byte(((databank << 16) | adr) & 0x7fffff, val);
}
}
-void xavix_device::mi_xavix_normal::write(uint16_t adr, uint8_t val)
+void xavix_device::mi_xavix::write(uint16_t adr, uint8_t val)
{
uint8_t databank = base->get_databank();
base->write_full_data(databank, adr, val);
}
-xavix_device::mi_xavix_nd::mi_xavix_nd(xavix_device *_base) : mi_xavix_normal(_base)
-{
-}
-
-uint8_t xavix_device::mi_xavix_nd::read_sync(uint16_t adr)
-{
- return sprogram->read_byte(base->adr_with_codebank(adr));
-}
-
-uint8_t xavix_device::mi_xavix_nd::read_arg(uint16_t adr)
-{
- return program->read_byte(base->adr_with_codebank(adr));
-}
-
void xavix_device::set_codebank(uint8_t bank)
{
// space().write_byte(0xfe, bank);
@@ -374,5 +373,4 @@ void xavix_device::state_string_export(const device_state_entry &entry, std::str
-
#include "cpu/m6502/xavix.hxx"
diff --git a/src/devices/cpu/m6502/xavix.h b/src/devices/cpu/m6502/xavix.h
index 89f97f574bd..5363bb77d36 100644
--- a/src/devices/cpu/m6502/xavix.h
+++ b/src/devices/cpu/m6502/xavix.h
@@ -135,22 +135,11 @@ public:
- typedef device_delegate<int16_t (int which, int half)> xavix_interrupt_vector_delegate;
-
- template <typename Object> void set_vector_callback(Object &&cb) { m_vector_callback = std::forward<Object>(cb); }
- void set_vector_callback(xavix_interrupt_vector_delegate callback) { m_vector_callback = callback; }
- template <class FunctionClass> void set_vector_callback(const char *devname, int16_t (FunctionClass::*callback)(int, int), const char *name)
- {
- set_vector_callback(xavix_interrupt_vector_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)));
- }
- template <class FunctionClass> void set_vector_callback(int16_t (FunctionClass::*callback)(int, int), const char *name)
- {
- set_vector_callback(xavix_interrupt_vector_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
- }
-
-
#undef O
+ typedef device_delegate<int16_t (int which, int half)> xavix_interrupt_vector_delegate;
+
+ template <typename... T> void set_vector_callback(T &&... args) { m_vector_callback.set(std::forward<T>(args)...); }
uint8_t read_full_data(uint8_t databank, uint16_t addr);
uint8_t read_full_data(uint32_t addr);
@@ -158,12 +147,12 @@ public:
void write_full_data(uint32_t addr, uint8_t val);
protected:
- class mi_xavix_normal : public memory_interface {
+ class mi_xavix : public memory_interface {
public:
xavix_device *base;
- mi_xavix_normal(xavix_device *base);
- virtual ~mi_xavix_normal() {}
+ mi_xavix(xavix_device *base);
+ virtual ~mi_xavix() {}
virtual uint8_t read(uint16_t adr) override;
virtual uint8_t read_sync(uint16_t adr) override;
@@ -171,15 +160,6 @@ protected:
virtual void write(uint16_t adr, uint8_t val) override;
};
- class mi_xavix_nd : public mi_xavix_normal {
- public:
- mi_xavix_nd(xavix_device *base);
- virtual ~mi_xavix_nd() {}
-
- virtual uint8_t read_sync(uint16_t adr) override;
- virtual uint8_t read_arg(uint16_t adr) override;
- };
-
uint8_t m_databank;
uint8_t m_codebank;
uint32_t XPC;
@@ -188,8 +168,8 @@ protected:
uint32_t adr_with_codebank(uint16_t adr) { return adr | (get_codebank() << 16); }
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual offs_t pc_to_external(u16 pc) override;
virtual void state_import(const device_state_entry &entry) override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
@@ -212,10 +192,10 @@ protected:
void set_databank(uint8_t bank);
uint8_t get_databank();
- void write_special_stack(uint8_t data);
+ void write_special_stack(uint32_t addr, uint8_t data);
void dec_special_stack();
void inc_special_stack();
- uint8_t read_special_stack();
+ uint8_t read_special_stack(uint32_t addr);
/* we store the additional 'codebank' used for far calls in a different, private stack
this seems to be neccessary for 'rad_hnt2' not to crash when bringing up the calibration / score table screens
@@ -231,6 +211,16 @@ protected:
uint8_t read_zeropage(uint32_t addr);
void write_zeropage(uint32_t addr, uint8_t val);
+ // Some original XaviX games seemed to suggest that the extra byte of the far calls went to a different
+ // stack, but dblmouse on suprtvpc does direct stack manipulation which challenges this assumption.
+ // It could be a SuperXaviX vs XaviX differences however, so currently leaving this as a toggle for testing.
+ //
+ // pausing in rad_hnt2 (press shift when on the map) is broken without this logic as the stack becomes too
+ // big with the extra bytes
+ //
+ // we currently use the private stack for regular XaviX but not for the later CPUs, however the root cause
+ // of needing it for regular XaviX could be somewhere else
+ bool m_use_private_stack_for_extra_callf_byte = true;
};
enum {
diff --git a/src/devices/cpu/m6502/xavix2000.cpp b/src/devices/cpu/m6502/xavix2000.cpp
index 94b56308e0d..328a357e23e 100644
--- a/src/devices/cpu/m6502/xavix2000.cpp
+++ b/src/devices/cpu/m6502/xavix2000.cpp
@@ -24,7 +24,6 @@
the 2002 chip seems to be the one that was officially dubbed 'SuperXaviX'
and has additional video capabilities on top of the extended opcodes.
-
***************************************************************************/
#include "emu.h"
@@ -39,10 +38,7 @@ DEFINE_DEVICE_TYPE(XAVIX2002, xavix2002_device, "xavix2002", "XaviX (SSD 2002) (
xavix2000_device::xavix2000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
xavix_device(mconfig, type, tag, owner, clock)
{
- program_config.m_addr_width = 24;
- program_config.m_logaddr_width = 24;
- sprogram_config.m_addr_width = 24;
- sprogram_config.m_logaddr_width = 24;
+ m_use_private_stack_for_extra_callf_byte = false;
}
xavix2000_device::xavix2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -60,10 +56,10 @@ void xavix2000_device::device_start()
{
xavix_device::device_start();
- state_add(SXAVIX_J, "J", m_j).callimport().formatstr("%8s");;
- state_add(SXAVIX_K, "K", m_k).callimport().formatstr("%8s");;
- state_add(SXAVIX_L, "L", m_l).callimport().formatstr("%8s");;
- state_add(SXAVIX_M, "M", m_m).callimport().formatstr("%8s");;
+ state_add(SXAVIX_J, "J", m_j).callimport().formatstr("%8s");
+ state_add(SXAVIX_K, "K", m_k).callimport().formatstr("%8s");
+ state_add(SXAVIX_L, "L", m_l).callimport().formatstr("%8s");
+ state_add(SXAVIX_M, "M", m_m).callimport().formatstr("%8s");
state_add(SXAVIX_PA, "PA", m_pa).callimport().formatstr("%8s");
state_add(SXAVIX_PB, "PB", m_pb).callimport().formatstr("%8s");
}
diff --git a/src/devices/cpu/m6502/xavix2000.h b/src/devices/cpu/m6502/xavix2000.h
index c5e3113e840..1416d919328 100644
--- a/src/devices/cpu/m6502/xavix2000.h
+++ b/src/devices/cpu/m6502/xavix2000.h
@@ -23,7 +23,7 @@ protected:
virtual void do_exec_full() override;
virtual void do_exec_partial() override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void state_import(const device_state_entry &entry) override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;