summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh2comn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh2comn.cpp')
-rw-r--r--src/devices/cpu/sh/sh2comn.cpp1204
1 files changed, 0 insertions, 1204 deletions
diff --git a/src/devices/cpu/sh/sh2comn.cpp b/src/devices/cpu/sh/sh2comn.cpp
deleted file mode 100644
index bb17a818c17..00000000000
--- a/src/devices/cpu/sh/sh2comn.cpp
+++ /dev/null
@@ -1,1204 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*****************************************************************************
- *
- * sh2common.c
- *
- * SH-2 non-specific components
- *
- *****************************************************************************/
-
-#include "emu.h"
-#include "sh2.h"
-#include "sh2comn.h"
-
-#include "debugger.h"
-
-//#define VERBOSE 1
-#include "logmacro.h"
-
-static const int div_tab[4] = { 3, 5, 7, 0 };
-
-
-void sh2_device::sh2_timer_resync()
-{
- // TODO: setting 3 is "External clock: count on rising edge"
- int divider = div_tab[m_frc_tcr & 3];
- uint64_t cur_time = total_cycles();
- uint64_t add = (cur_time - m_frc_base) >> divider;
-
- if (add > 0)
- {
- if(divider)
- m_frc += add;
-
- m_frc_base = cur_time;
- }
-}
-
-void sh2_device::sh2_timer_activate()
-{
- int max_delta = 0xfffff;
- uint16_t frc;
-
- m_timer->adjust(attotime::never);
-
- frc = m_frc;
- if(!(m_ftcsr & OCFA)) {
- uint16_t delta = m_ocra - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(!(m_ftcsr & OCFB) && (m_ocra <= m_ocrb || !(m_ftcsr & CCLRA))) {
- uint16_t delta = m_ocrb - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(!(m_ftcsr & OVF) && !(m_ftcsr & CCLRA)) {
- int delta = 0x10000 - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(max_delta != 0xfffff) {
- int divider = div_tab[m_frc_tcr & 3];
- if(divider) {
- max_delta <<= divider;
- m_frc_base = total_cycles();
- m_timer->adjust(cycles_to_attotime(max_delta));
- } else {
- logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta);
- }
- }
-}
-
-TIMER_CALLBACK_MEMBER( sh2_device::sh2_timer_callback )
-{
- uint16_t frc;
-
- sh2_timer_resync();
-
- frc = m_frc;
-
- if(frc == m_ocrb)
- m_ftcsr |= OCFB;
-
- if(frc == 0x0000)
- m_ftcsr |= OVF;
-
- if(frc == m_ocra)
- {
- m_ftcsr |= OCFA;
-
- if(m_ftcsr & CCLRA)
- m_frc = 0;
- }
-
- sh2_recalc_irq();
- sh2_timer_activate();
-}
-
-
-/*
- We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it.
- The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most
- can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible
- because the game is expecting the 68k of the system to feed data into the FIFO at the same
- time as the SH2 is transfering it out via DMA
-
- There are two ways we can do this
-
- a) with a high frequency timer (more accurate, but a large performance hit)
-
- or
-
- b) in the CPU_EXECUTE loop
-
-
- we're currently doing a)
-
- b) causes problems with ST-V games
-
-*/
-
-
-
-void sh2_device::sh2_notify_dma_data_available()
-{
- //printf("call notify\n");
-
- for (int dmach=0;dmach<2;dmach++)
- {
- //printf("m_dma_timer_active[dmach] %04x\n",m_dma_timer_active[dmach]);
-
- if (m_dma_timer_active[dmach]==2) // 2 = stalled
- {
- // printf("resuming stalled dma\n");
- m_dma_timer_active[dmach]=1;
- m_dma_current_active_timer[dmach]->adjust(attotime::zero, dmach);
- }
- }
-
-}
-
-void sh2_device::sh2_do_dma(int dmach)
-{
- uint32_t dmadata;
-
- uint32_t tempsrc, tempdst;
-
- if (m_active_dma_count[dmach] > 0)
- {
- // process current DMA
- switch(m_active_dma_size[dmach])
- {
- case 0:
- {
- // we need to know the src / dest ahead of time without changing them
- // to allow for the callback to check if we can process the DMA at this
- // time (we need to know where we're reading / writing to/from)
-
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 1;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 1;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_byte(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_byte(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] --;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] --;
-
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] ++;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] ++;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 1:
- {
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 2;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 2;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- // check: should this really be using read_word_32 / write_word_32?
- dmadata = m_program->read_word(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_word(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] -= 2;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 2;
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] += 2;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 2;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 2:
- {
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 4;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 4;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_dword(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] -= 4;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 4;
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] += 4;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 4;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 3:
- {
- // shouldn't this really be 4 calls here instead?
-
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 16;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n");
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_dword(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+4);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+4, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+8);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+8, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+12);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+12, dmadata);
-
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 16;
-
- m_active_dma_src[dmach] += 16;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 16;
-
- m_active_dma_count[dmach]-=4;
- }
- break;
- }
- }
- else // the dma is complete
- {
- // int dma = param & 1;
-
- // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished
- if (m_active_dma_steal[dmach])
- {
- resume(SUSPEND_REASON_HALT );
- }
-
-
- LOG("SH2: DMA %d complete\n", dmach);
- m_dmac[dmach].tcr = 0;
- m_dmac[dmach].chcr |= 2;
- m_dma_timer_active[dmach] = 0;
- m_dma_irq[dmach] |= 1;
- sh2_recalc_irq();
-
- }
-}
-
-TIMER_CALLBACK_MEMBER( sh2_device::sh2_dma_current_active_callback )
-{
- int dma = param & 1;
-
- sh2_do_dma(dma);
-}
-
-
-void sh2_device::sh2_dmac_check(int dmach)
-{
- if(m_dmac[dmach].chcr & m_dmaor & 1)
- {
- if(!m_dma_timer_active[dmach] && !(m_dmac[dmach].chcr & 2))
- {
- m_active_dma_incd[dmach] = (m_dmac[dmach].chcr >> 14) & 3;
- m_active_dma_incs[dmach] = (m_dmac[dmach].chcr >> 12) & 3;
- m_active_dma_size[dmach] = (m_dmac[dmach].chcr >> 10) & 3;
- m_active_dma_steal[dmach] = (m_dmac[dmach].chcr & 0x10);
-
- if(m_active_dma_incd[dmach] == 3 || m_active_dma_incs[dmach] == 3)
- {
- logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dmach], m_active_dma_incs[dmach], m_active_dma_size[dmach], m_dmac[dmach].chcr);
- return;
- }
- m_active_dma_src[dmach] = m_dmac[dmach].sar;
- m_active_dma_dst[dmach] = m_dmac[dmach].dar;
- m_active_dma_count[dmach] = m_dmac[dmach].tcr;
- if(!m_active_dma_count[dmach])
- m_active_dma_count[dmach] = 0x1000000;
-
- LOG("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dmach, m_active_dma_src[dmach], m_active_dma_dst[dmach], m_active_dma_count[dmach], m_dmac[dmach].chcr, m_active_dma_incs[dmach], m_active_dma_incd[dmach], m_active_dma_size[dmach]);
-
- m_dma_timer_active[dmach] = 1;
-
- m_active_dma_src[dmach] &= SH12_AM;
- m_active_dma_dst[dmach] &= SH12_AM;
-
- switch(m_active_dma_size[dmach])
- {
- case 0:
- break;
- case 1:
- m_active_dma_src[dmach] &= ~1;
- m_active_dma_dst[dmach] &= ~1;
- break;
- case 2:
- m_active_dma_src[dmach] &= ~3;
- m_active_dma_dst[dmach] &= ~3;
- break;
- case 3:
- m_active_dma_src[dmach] &= ~3;
- m_active_dma_dst[dmach] &= ~3;
- m_active_dma_count[dmach] &= ~3;
- break;
- }
-
- // start DMA timer
-
- // fever soccer uses cycle-stealing mode, requiring the CPU to be halted
- if (m_active_dma_steal[dmach])
- {
- //printf("cycle stealing DMA\n");
- suspend(SUSPEND_REASON_HALT, 1 );
- }
-
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
- }
- }
- else
- {
- if(m_dma_timer_active[dmach])
- {
- logerror("SH2: DMA %d cancelled in-flight\n", dmach);
- //m_dma_complete_timer[dmach]->adjust(attotime::never);
- m_dma_current_active_timer[dmach]->adjust(attotime::never, dmach);
-
- m_dma_timer_active[dmach] = 0;
- }
- }
-}
-
-/*
- * SCI
- */
-// TODO: identical to H8 counterpart
-
-READ8_MEMBER( sh2_device::smr_r )
-{
- return m_smr;
-}
-
-WRITE8_MEMBER( sh2_device::smr_w )
-{
- m_smr = data;
-}
-
-READ8_MEMBER( sh2_device::brr_r )
-{
- return m_brr;
-}
-
-WRITE8_MEMBER( sh2_device::brr_w )
-{
- m_brr = data;
-}
-
-READ8_MEMBER( sh2_device::scr_r )
-{
- return m_scr;
-}
-
-WRITE8_MEMBER( sh2_device::scr_w )
-{
- m_scr = data;
-}
-
-READ8_MEMBER( sh2_device::tdr_r )
-{
- return m_tdr;
-}
-
-WRITE8_MEMBER( sh2_device::tdr_w )
-{
- m_tdr = data;
- // printf("%c",data & 0xff);
-}
-
-READ8_MEMBER( sh2_device::ssr_r )
-{
- // 0x84 is needed by EGWord on Saturn to make it to boot for some reason.
- return m_ssr | 0x84;
-}
-
-WRITE8_MEMBER( sh2_device::ssr_w )
-{
- m_ssr = data;
-}
-
-READ8_MEMBER( sh2_device::rdr_r )
-{
- return 0;
-}
-
-/*
- * FRC
- */
-
-READ8_MEMBER( sh2_device::tier_r )
-{
- return m_tier;
-}
-
-WRITE8_MEMBER( sh2_device::tier_w )
-{
- sh2_timer_resync();
- m_tier = data;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::ftcsr_r )
-{
- // TODO: to be tested
- if (!m_ftcsr_read_cb.isnull())
- m_ftcsr_read_cb((((m_tier<<24) | (m_ftcsr<<16)) & 0xffff0000) | m_frc);
-
- return m_ftcsr;
-}
-
-WRITE8_MEMBER( sh2_device::ftcsr_w )
-{
- uint8_t old;
- old = m_ftcsr;
-
- m_ftcsr = data;
- sh2_timer_resync();
- m_ftcsr = (m_ftcsr & ~(ICF|OCFA|OCFB|OVF)) | (old & m_ftcsr & (ICF|OCFA|OCFB|OVF));
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::frc_r )
-{
- sh2_timer_resync();
- return m_frc;
-}
-
-WRITE16_MEMBER( sh2_device::frc_w )
-{
- sh2_timer_resync();
- COMBINE_DATA(&m_frc);
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::ocra_b_r )
-{
- return (m_tocr & 0x10) ? m_ocrb : m_ocra;
-}
-
-WRITE16_MEMBER( sh2_device::ocra_b_w )
-{
- sh2_timer_resync();
- if(m_tocr & 0x10)
- m_ocrb = (m_ocrb & (~mem_mask)) | (data & mem_mask);
- else
- m_ocra = (m_ocra & (~mem_mask)) | (data & mem_mask);
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::frc_tcr_r )
-{
- return m_frc_tcr & 0x83;
-}
-
-WRITE8_MEMBER( sh2_device::frc_tcr_w )
-{
- sh2_timer_resync();
- m_frc_tcr = data & 0x83;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::tocr_r )
-{
- return (m_tocr & 0x13) | 0xe0;
-}
-
-WRITE8_MEMBER( sh2_device::tocr_w )
-{
- sh2_timer_resync();
- // TODO: output levels A/B (bits 1-0)
- m_tocr = data & 0x13;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::frc_icr_r )
-{
- return m_frc_icr;
-}
-
-/*
- * INTC
- */
-
-READ16_MEMBER( sh2_device::intc_icr_r )
-{
- // TODO: flip meaning based off NMI edge select bit (NMIE)
- uint16_t nmilv = m_nmi_line_state == ASSERT_LINE ? 0 : 0x8000;
- return (nmilv) | (m_intc_icr & 0x0101);
-}
-
-WRITE16_MEMBER( sh2_device::intc_icr_w )
-{
- COMBINE_DATA(&m_intc_icr);
- m_nmie = bool(BIT(m_intc_icr, 8));
- m_vecmd = bool(BIT(m_intc_icr, 0));
-}
-
-READ16_MEMBER( sh2_device::ipra_r )
-{
- return m_ipra & 0xfff0;
-}
-
-WRITE16_MEMBER( sh2_device::ipra_w )
-{
- COMBINE_DATA(&m_ipra);
- m_irq_level.divu = (m_ipra >> 12) & 0xf;
- m_irq_level.dmac = (m_ipra >> 8) & 0xf;
- m_irq_level.wdt = (m_ipra >> 4) & 0xf;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::iprb_r )
-{
- return m_iprb & 0xff00;
-}
-
-WRITE16_MEMBER( sh2_device::iprb_w )
-{
- COMBINE_DATA(&m_iprb);
- m_irq_level.sci = (m_iprb >> 12) & 0xf;
- m_irq_level.frc = (m_iprb >> 8) & 0xf;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcra_r )
-{
- return m_vcra & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcra_w )
-{
- COMBINE_DATA(&m_vcra);
- // ...
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrb_r )
-{
- return m_vcrb;
-}
-
-WRITE16_MEMBER( sh2_device::vcrb_w )
-{
- COMBINE_DATA(&m_vcrb);
- // ...
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrc_r )
-{
- return m_vcrc & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcrc_w )
-{
- COMBINE_DATA(&m_vcrc);
- m_irq_vector.fic = (m_vcrc >> 8) & 0x7f;
- m_irq_vector.foc = (m_vcrc >> 0) & 0x7f;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrd_r )
-{
- return m_vcrd & 0x7f00;
-}
-
-WRITE16_MEMBER( sh2_device::vcrd_w )
-{
- COMBINE_DATA(&m_vcrd);
- m_irq_vector.fov = (m_vcrc >> 8) & 0x7f;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrwdt_r )
-{
- return m_vcrwdt & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcrwdt_w )
-{
- COMBINE_DATA(&m_vcrwdt);
- // ...
- sh2_recalc_irq();
-}
-
-READ32_MEMBER( sh2_device::vcrdiv_r )
-{
- return m_vcrdiv & 0x7f;
-}
-
-WRITE32_MEMBER( sh2_device::vcrdiv_w )
-{
- COMBINE_DATA(&m_vcrdiv);
- // TODO: unemulated, level is seemingly not documented/settable?
- m_irq_vector.divu = data & 0x7f;
- sh2_recalc_irq();
-}
-
-/*
- * DIVU
- */
-
-READ32_MEMBER( sh2_device::dvcr_r )
-{
- return (m_divu_ovfie == true ? 2 : 0) | (m_divu_ovf == true ? 1 : 0);
-}
-
-WRITE32_MEMBER( sh2_device::dvcr_w )
-{
- if(ACCESSING_BITS_0_7)
- {
- if (data & 1)
- m_divu_ovf = false;
- if (data & 2)
- {
- m_divu_ovfie = bool(BIT(data, 1));
- if (m_divu_ovfie == true)
- logerror("SH2: unemulated DIVU OVF interrupt enable\n");
- }
- sh2_recalc_irq();
- }
-}
-
-READ32_MEMBER( sh2_device::dvsr_r )
-{
- return m_dvsr;
-}
-
-WRITE32_MEMBER( sh2_device::dvsr_w )
-{
- COMBINE_DATA(&m_dvsr);
-}
-
-READ32_MEMBER( sh2_device::dvdnt_r )
-{
- return m_dvdntl;
-}
-
-WRITE32_MEMBER( sh2_device::dvdnt_w )
-{
- COMBINE_DATA(&m_dvdntl);
- int32_t a = m_dvdntl;
- int32_t b = m_dvsr;
- LOG("SH2 div32+mod %d/%d\n", a, b);
- if (b)
- {
- m_dvdntl = a / b;
- m_dvdnth = a % b;
- }
- else
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
-}
-
-READ32_MEMBER( sh2_device::dvdnth_r )
-{
- return m_dvdnth;
-}
-
-READ32_MEMBER( sh2_device::dvdntl_r )
-{
- return m_dvdntl;
-}
-
-WRITE32_MEMBER( sh2_device::dvdnth_w )
-{
- COMBINE_DATA(&m_dvdnth);
-}
-
-WRITE32_MEMBER( sh2_device::dvdntl_w )
-{
- COMBINE_DATA(&m_dvdntl);
- int64_t a = m_dvdntl | ((uint64_t)(m_dvdnth) << 32);
- int64_t b = (int32_t)m_dvsr;
- LOG("SH2 div64+mod %d/%d\n", a, b);
- if (b)
- {
- int64_t q = a / b;
- if (q != (int32_t)q)
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
- else
- {
- m_dvdntl = q;
- m_dvdnth = a % b;
- }
- }
- else
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
-}
-
-/*
- * WTC
- */
-
-READ16_MEMBER( sh2_device::wtcnt_r )
-{
- return ((m_wtcsr | 0x18) << 8) | (m_wtcnt & 0xff);
-}
-
-READ16_MEMBER( sh2_device::rstcsr_r )
-{
- return (m_rstcsr & 0xe0) | 0x1f;
-}
-
-WRITE16_MEMBER( sh2_device::wtcnt_w )
-{
- COMBINE_DATA(&m_wtcw[0]);
- switch (m_wtcw[0] & 0xff00)
- {
- case 0x5a00:
- m_wtcnt = m_wtcw[0] & 0xff;
- break;
- case 0xa500:
- /*
- WTCSR
- x--- ---- Overflow in IT mode
- -x-- ---- Timer mode (0: IT 1: watchdog)
- --x- ---- Timer enable
- ---1 1---
- ---- -xxx Clock select
- */
- m_wtcsr = m_wtcw[0] & 0xff;
- break;
- }
-}
-
-WRITE16_MEMBER( sh2_device::rstcsr_w )
-{
- COMBINE_DATA(&m_wtcw[1]);
- switch (m_wtcw[1] & 0xff00)
- {
- case 0xa500:
- // clear WOVF flag
- if ((m_wtcw[1] & 0x80) == 0)
- m_rstcsr &= 0x7f;
- break;
- case 0x5a00:
- m_rstcsr = (m_rstcsr & 0x80) | (m_wtcw[1] & 0x60);
- break;
- }
-}
-
-READ16_MEMBER( sh2_device::fmr_sbycr_r )
-{
- return m_sbycr;
-}
-
-WRITE16_MEMBER( sh2_device::fmr_sbycr_w )
-{
- switch (mem_mask)
- {
- case 0xff00: // FMR 8bit
- logerror("SH2 set clock multiplier x%d\n", 1 << ((data >> 8) & 3));
- break;
- case 0xffff: // FMR 16bit
- // SH7604 docs says FMR register must be set using 8-bit write, however at practice 16-bit works too.
- // has been verified for CPS3 custom SH2, SH7604 and SH7095 (clock multiplier feature is not officially documented for SH7095).
- logerror("SH2 set clock multiplier x%d\n", 1 << (data & 3));
- break;
- case 0x00ff: // SBYCR
- m_sbycr = data;
- if (data & 0x1f)
- logerror("SH2 module stop selected %02x\n", data);
- break;
- }
-}
-
-READ8_MEMBER( sh2_device::ccr_r )
-{
- return m_ccr & ~0x30;
-}
-
-WRITE8_MEMBER( sh2_device::ccr_w )
-{
- /*
- xx-- ---- Way 0/1
- ---x ---- Cache Purge (CP), write only
- ---- x--- Two-Way Mode (TW)
- ---- -x-- Data Replacement Disable (OD)
- ---- --x- Instruction Replacement Disable (ID)
- ---- ---x Cache Enable (CE)
- */
- m_ccr = data;
-}
-
-READ32_MEMBER( sh2_device::bcr1_r )
-{
- return (m_bcr1 & ~0xe008) | (m_is_slave ? 0x8000 : 0);
-}
-
-WRITE32_MEMBER( sh2_device::bcr1_w )
-{
- COMBINE_DATA(&m_bcr1);
-}
-
-READ32_MEMBER( sh2_device::bcr2_r )
-{
- return m_bcr2;
-}
-
-WRITE32_MEMBER( sh2_device::bcr2_w )
-{
- COMBINE_DATA(&m_bcr2);
-}
-
-READ32_MEMBER( sh2_device::wcr_r )
-{
- return m_wcr;
-}
-
-WRITE32_MEMBER( sh2_device::wcr_w )
-{
- COMBINE_DATA(&m_wcr);
-}
-
-READ32_MEMBER( sh2_device::mcr_r )
-{
- return m_mcr & ~0x103;
-}
-
-WRITE32_MEMBER( sh2_device::mcr_w )
-{
- COMBINE_DATA(&m_mcr);
-}
-
-READ32_MEMBER( sh2_device::rtcsr_r )
-{
- return m_rtcsr & 0xf8;
-}
-
-WRITE32_MEMBER( sh2_device::rtcsr_w )
-{
- COMBINE_DATA(&m_rtcsr);
-}
-
-READ32_MEMBER( sh2_device::rtcnt_r )
-{
- return m_rtcnt & 0xff;
-}
-
-WRITE32_MEMBER( sh2_device::rtcnt_w )
-{
- COMBINE_DATA(&m_rtcnt);
- m_rtcnt &= 0xff;
-}
-
-READ32_MEMBER( sh2_device::rtcor_r )
-{
- return m_rtcor & 0xff;
-}
-
-WRITE32_MEMBER( sh2_device::rtcor_w )
-{
- COMBINE_DATA(&m_rtcor);
- m_rtcor &= 0xff;
-}
-
-void sh2_device::set_frt_input(int state)
-{
- if(m_frt_input == state) {
- return;
- }
-
- m_frt_input = state;
-
- if(m_frc_tcr & 0x80) {
- if(state == CLEAR_LINE) {
- return;
- }
- } else {
- if(state == ASSERT_LINE) {
- return;
- }
- }
-
- sh2_timer_resync();
- m_frc_icr = m_frc;
- m_ftcsr |= ICF;
- //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM);
- sh2_recalc_irq();
-}
-
-void sh2_device::sh2_recalc_irq()
-{
- int irq = 0, vector = -1;
- int level;
-
- // Timer irqs
- if (m_tier & m_ftcsr & (ICF|OCFA|OCFB|OVF))
- {
- level = (m_irq_level.frc & 15);
- if (level > irq)
- {
- int mask = m_tier & m_ftcsr;
- irq = level;
- if(mask & ICF)
- vector = m_irq_vector.fic & 0x7f;
- else if(mask & (OCFA|OCFB))
- vector = m_irq_vector.foc & 0x7f;
- else
- vector = m_irq_vector.fov & 0x7f;
- }
- }
-
- // DMA irqs
- if((m_dmac[0].chcr & 6) == 6 && m_dma_irq[0]) {
- level = m_irq_level.dmac & 15;
- if(level > irq) {
- irq = level;
- m_dma_irq[0] &= ~1;
- vector = m_irq_vector.dmac[0] & 0x7f;
- }
- }
- else if((m_dmac[1].chcr & 6) == 6 && m_dma_irq[1]) {
- level = m_irq_level.dmac & 15;
- if(level > irq) {
- irq = level;
- m_dma_irq[1] &= ~1;
- vector = m_irq_vector.dmac[1] & 0x7f;
- }
- }
-
- m_sh2_state->internal_irq_level = irq;
- m_internal_irq_vector = vector;
- m_test_irq = 1;
-}
-
-/*
- SH-7021 on-chip device
- */
-
-void sh2a_device::sh7032_dma_exec(int ch)
-{
- const short dma_word_size[4] = { 0, +1, -1, 0 };
- uint8_t rs = (m_dma[ch].chcr >> 8) & 0xf; /**< Resource Select bits */
- if(rs != 0xc) // Auto-Request
- {
- logerror("Warning: SH7032 DMA enables non auto-request transfer\n");
- return;
- }
-
- // channel enable & master enable
- if((m_dma[ch].chcr & 1) == 0 || (m_dmaor & 1) == 0)
- return;
-
- printf("%08x %08x %04x\n",m_dma[ch].sar,m_dma[ch].dar,m_dma[ch].chcr);
- uint8_t dm = (m_dma[ch].chcr >> 14) & 3; /**< Destination Address Mode bits */
- uint8_t sm = (m_dma[ch].chcr >> 12) & 3; /**< Source Address Mode bits */
- bool ts = (m_dma[ch].chcr & 8); /**< Transfer Size bit */
- int src_word_size = dma_word_size[sm] * ((ts == true) ? 2 : 1);
- int dst_word_size = dma_word_size[dm] * ((ts == true) ? 2 : 1);
- uint32_t src_addr = m_dma[ch].sar;
- uint32_t dst_addr = m_dma[ch].dar;
- uint32_t size_index = m_dma[ch].tcr;
- if(size_index == 0)
- size_index = 0x10000;
-
- if(ts == false)
- logerror("SH7032: DMA byte mode check\n");
-
- for(int index = size_index;index>-1;index--)
- {
- if(ts == true)
- m_program->write_word(dst_addr,m_program->read_word(src_addr));
- else
- m_program->write_byte(dst_addr,m_program->read_byte(src_addr));
-
- src_addr += src_word_size;
- dst_addr += dst_word_size;
- }
-
- m_dma[ch].chcr &= ~1; /**< @todo non-instant DMA */
- printf("%02x %02x %02x %1d\n",sm,dm,rs,ts);
-}
-
-READ32_MEMBER(sh2a_device::dma_sar0_r)
-{
- return m_dma[0].sar;
-}
-
-WRITE32_MEMBER(sh2a_device::dma_sar0_w)
-{
- COMBINE_DATA(&m_dma[0].sar);
-}
-
-READ32_MEMBER(sh2a_device::dma_dar0_r)
-{
- return m_dma[0].dar;
-}
-
-WRITE32_MEMBER(sh2a_device::dma_dar0_w)
-{
- COMBINE_DATA(&m_dma[0].dar);
-}
-
-READ16_MEMBER(sh2a_device::dma_tcr0_r)
-{
- return m_dma[0].tcr;
-}
-
-WRITE16_MEMBER(sh2a_device::dma_tcr0_w)
-{
- //printf("%04x\n",data);
- COMBINE_DATA(&m_dma[0].tcr);
-}
-
-READ16_MEMBER(sh2a_device::dma_chcr0_r)
-{
- return m_dma[0].chcr;
-}
-
-WRITE16_MEMBER(sh2a_device::dma_chcr0_w)
-{
- //printf("%04x CHCR0\n",data);
- COMBINE_DATA(&m_dma[0].chcr);
- sh7032_dma_exec(0);
-}
-
-READ16_MEMBER(sh2a_device::dmaor_r)
-{
- return m_dmaor;
-}
-
-WRITE16_MEMBER(sh2a_device::dmaor_w)
-{
- COMBINE_DATA(&m_dmaor);
- sh7032_dma_exec(0);
-}
-
-/*!
- @brief Dummy debug interface
- */
-READ16_MEMBER(sh1_device::sh7032_r)
-{
- return m_sh7032_regs[offset];
-}
-
-/*!
- @brief Dummy debug interface
- */
-WRITE16_MEMBER(sh1_device::sh7032_w)
-{
- COMBINE_DATA(&m_sh7032_regs[offset]);
-}
-
-READ16_MEMBER(sh2a_device::sh7021_r)
-{
- return m_sh7021_regs[offset];
-}
-
-/*!
- @brief Dummy debug interface
- */
-WRITE16_MEMBER(sh2a_device::sh7021_w)
-{
- COMBINE_DATA(&m_sh7021_regs[offset]);
-}