diff options
Diffstat (limited to 'src/devices/cpu/m6502')
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; |