diff options
author | 2011-10-09 23:09:13 +0000 | |
---|---|---|
committer | 2011-10-09 23:09:13 +0000 | |
commit | 6d00689c35c7f0891857d413108d4ce1e5662e5f (patch) | |
tree | 31db75430b3cadd3322154a0f4a3fa9ebacc8748 /src/emu | |
parent | f8aba531d3c7c43c01bdb32161b00f71f634d8ce (diff) |
Preliminary hook up of sh3 dma from Haze + flash access code from Luca. (nw)
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/cpu/cpu.mak | 12 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh3comn.c | 41 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh3comn.h | 20 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4.c | 9 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4comn.c | 629 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4comn.h | 23 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4dmac.c | 686 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4dmac.h | 63 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4regs.h | 57 |
9 files changed, 920 insertions, 620 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 9b83197d3b5..31dc2a50210 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -532,7 +532,7 @@ $(CPUOBJ)/sh2/sh2fe.o: $(CPUSRC)/sh2/sh2fe.c \ ifneq ($(filter SH4,$(CPUS)),) OBJDIRS += $(CPUOBJ)/sh4 -CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o +CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o $(CPUOBJ)/sh4/sh4dmac.o DASMOBJS += $(CPUOBJ)/sh4/sh4dasm.o endif @@ -560,6 +560,16 @@ $(CPUOBJ)/sh4/sh4tmu.o: $(CPUSRC)/sh4/sh4tmu.c \ $(CPUSRC)/sh4/sh4comn.h \ $(CPUSRC)/sh4/sh3comn.h +$(CPUOBJ)/sh4/sh4dmac.o: $(CPUSRC)/sh4/sh4dmac.c \ + $(CPUSRC)/sh4/sh4dmac.h \ + $(CPUSRC)/sh4/sh3comn.c \ + $(CPUSRC)/sh4/sh3comn.h \ + $(CPUSRC)/sh4/sh4.c \ + $(CPUSRC)/sh4/sh4.h \ + $(CPUSRC)/sh4/sh4regs.h \ + $(CPUSRC)/sh4/sh4comn.h \ + $(CPUSRC)/sh4/sh3comn.h + #------------------------------------------------- # Hudsonsoft 6280 #------------------------------------------------- diff --git a/src/emu/cpu/sh4/sh3comn.c b/src/emu/cpu/sh4/sh3comn.c index 0b2dc4bf443..dbdaaaa3e4e 100644 --- a/src/emu/cpu/sh4/sh3comn.c +++ b/src/emu/cpu/sh4/sh3comn.c @@ -6,6 +6,8 @@ #include "sh4comn.h" #include "sh3comn.h" #include "sh4tmu.h" +#include "sh4dmac.h" + /* High internal area (ffffxxxx) */ WRITE32_HANDLER( sh3_internal_high_w ) @@ -145,6 +147,26 @@ READ32_HANDLER( sh3_internal_r ) switch (offset) { + + case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask); + case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask); + case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask); + case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask); + case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask); + case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask); + case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask); + case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask); + case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask); + case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask); + case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask); + case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask); + case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask); + case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask); + case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask); + case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask); + case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask)<<16; + + case INTEVT2: { // logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+0x4000000,mem_mask); @@ -248,6 +270,25 @@ WRITE32_HANDLER( sh3_internal_w ) switch (offset) { + case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break; + case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break; + case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break; + case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break; + case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break; + case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break; + case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break; + case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break; + case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break; + case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break; + case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break; + case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break; + case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break; + case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break; + case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break; + case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break; + case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data>>16,mem_mask>>16); break; + + case IRR0_IRR1: { { diff --git a/src/emu/cpu/sh4/sh3comn.h b/src/emu/cpu/sh4/sh3comn.h index 6c1271b68c2..f701f3f1bf6 100644 --- a/src/emu/cpu/sh4/sh3comn.h +++ b/src/emu/cpu/sh4/sh3comn.h @@ -11,6 +11,26 @@ #define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4) #define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4) #define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4) + +#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4) +#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4) + + #define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4) #define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4) #define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4) diff --git a/src/emu/cpu/sh4/sh4.c b/src/emu/cpu/sh4/sh4.c index 93735b5f9c2..2c383a7d474 100644 --- a/src/emu/cpu/sh4/sh4.c +++ b/src/emu/cpu/sh4/sh4.c @@ -3313,7 +3313,14 @@ static CPU_RESET( sh3 ) CPU_RESET_CALL(common_sh4_reset); sh4->cpu_type = CPU_TYPE_SH3; - + + sh4->SH4_TCOR0 = 0xffffffff; + sh4->SH4_TCNT0 = 0xffffffff; + sh4->SH4_TCOR1 = 0xffffffff; + sh4->SH4_TCNT1 = 0xffffffff; + sh4->SH4_TCOR2 = 0xffffffff; + sh4->SH4_TCNT2 = 0xffffffff; + } static CPU_RESET( sh4 ) diff --git a/src/emu/cpu/sh4/sh4comn.c b/src/emu/cpu/sh4/sh4comn.c index 340e318555f..051576af4fb 100644 --- a/src/emu/cpu/sh4/sh4comn.c +++ b/src/emu/cpu/sh4/sh4comn.c @@ -13,11 +13,11 @@ #include "sh4comn.h" #include "sh3comn.h" #include "sh4tmu.h" - +#include "sh4dmac.h" static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 }; static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 }; + static const UINT32 exception_priority_default[] = { @@ -627,280 +627,11 @@ static TIMER_CALLBACK( sh4_rtc_timer_callback ) } -static TIMER_CALLBACK( sh4_dmac_callback ) -{ - sh4_state *sh4 = (sh4_state *)ptr; - int channel = param; - - if (sh4->cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_dmac_callback uses sh4->m[] with SH3\n"); - - LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel)); - sh4->dma_timer_active[channel] = 0; - switch (channel) - { - case 0: - sh4->m[DMATCR0] = 0; - sh4->m[CHCR0] |= CHCR_TE; - if (sh4->m[CHCR0] & CHCR_IE) - sh4_exception_request(sh4, SH4_INTC_DMTE0); - break; - case 1: - sh4->m[DMATCR1] = 0; - sh4->m[CHCR1] |= CHCR_TE; - if (sh4->m[CHCR1] & CHCR_IE) - sh4_exception_request(sh4, SH4_INTC_DMTE1); - break; - case 2: - sh4->m[DMATCR2] = 0; - sh4->m[CHCR2] |= CHCR_TE; - if (sh4->m[CHCR2] & CHCR_IE) - sh4_exception_request(sh4, SH4_INTC_DMTE2); - break; - case 3: - sh4->m[DMATCR3] = 0; - sh4->m[CHCR3] |= CHCR_TE; - if (sh4->m[CHCR3] & CHCR_IE) - sh4_exception_request(sh4, SH4_INTC_DMTE3); - break; - } -} - -static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr) -{ - int incs, incd, size; - UINT32 src, dst, count; - - incd = (chcr & CHCR_DM) >> 14; - incs = (chcr & CHCR_SM) >> 12; - size = dmasize[(chcr & CHCR_TS) >> 4]; - if(incd == 3 || incs == 3) - { - logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); - return 0; - } - src = *sar; - dst = *dar; - count = *dmatcr; - if (!count) - count = 0x1000000; - - LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); - - if (timermode == 1) // timer actvated after a time based on the number of words to transfer - { - sh4->dma_timer_active[channel] = 1; - sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel); - } - else if (timermode == 2) // timer activated immediately - { - sh4->dma_timer_active[channel] = 1; - sh4->dma_timer[channel]->adjust(attotime::zero, channel); - } - - src &= AM; - dst &= AM; - - switch(size) - { - case 1: // 8 bit - for(;count > 0; count --) - { - if(incs == 2) - src --; - if(incd == 2) - dst --; - sh4->program->write_byte(dst, sh4->program->read_byte(src)); - if(incs == 1) - src ++; - if(incd == 1) - dst ++; - } - break; - case 2: // 16 bit - src &= ~1; - dst &= ~1; - for(;count > 0; count --) - { - if(incs == 2) - src -= 2; - if(incd == 2) - dst -= 2; - sh4->program->write_word(dst, sh4->program->read_word(src)); - if(incs == 1) - src += 2; - if(incd == 1) - dst += 2; - } - break; - case 8: // 64 bit - src &= ~7; - dst &= ~7; - for(;count > 0; count --) - { - if(incs == 2) - src -= 8; - if(incd == 2) - dst -= 8; - sh4->program->write_qword(dst, sh4->program->read_qword(src)); - if(incs == 1) - src += 8; - if(incd == 1) - dst += 8; - - } - break; - case 4: // 32 bit - src &= ~3; - dst &= ~3; - for(;count > 0; count --) - { - if(incs == 2) - src -= 4; - if(incd == 2) - dst -= 4; - sh4->program->write_dword(dst, sh4->program->read_dword(src)); - if(incs == 1) - src += 4; - if(incd == 1) - dst += 4; - - } - break; - case 32: - src &= ~31; - dst &= ~31; - for(;count > 0; count --) - { - if(incs == 2) - src -= 32; - if(incd == 2) - dst -= 32; - sh4->program->write_qword(dst, sh4->program->read_qword(src)); - sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8)); - sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16)); - sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24)); - if(incs == 1) - src += 32; - if(incd == 1) - dst += 32; - } - break; - } - *sar = (*sar & !AM) | src; - *dar = (*dar & !AM) | dst; - *dmatcr = count; - return 1; -} - -static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr) -{ - int incs, incd, size, mod; - UINT32 src, dst, count; - - incd = (chcr & CHCR_DM) >> 14; - incs = (chcr & CHCR_SM) >> 12; - size = dmasize[(chcr & CHCR_TS) >> 4]; - mod = ((chcr & CHCR_RS) >> 8); - if (incd == 3 || incs == 3) - { - logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); - return 0; - } - src = *sar; - dst = *dar; - count = *dmatcr; - if (!count) - count = 0x1000000; - - LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); - - sh4->dma_timer_active[channel] = 1; - - src &= AM; - dst &= AM; - - // remember parameters - sh4->dma_source[channel]=src; - sh4->dma_destination[channel]=dst; - sh4->dma_count[channel]=count; - sh4->dma_wordsize[channel]=size; - sh4->dma_source_increment[channel]=incs; - sh4->dma_destination_increment[channel]=incd; - sh4->dma_mode[channel]=mod; - - // inform device its ready to transfer - sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16)); - return 1; -} - -static void sh4_dmac_check(sh4_state *sh4, int channel) -{ -UINT32 dmatcr, chcr, sar, dar; - - if (sh4->cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_dmac_check uses sh4->m[] with SH3\n"); - - switch (channel) - { - case 0: - sar = sh4->m[SAR0]; - dar = sh4->m[DAR0]; - chcr = sh4->m[CHCR0]; - dmatcr = sh4->m[DMATCR0]; - break; - case 1: - sar = sh4->m[SAR1]; - dar = sh4->m[DAR1]; - chcr = sh4->m[CHCR1]; - dmatcr = sh4->m[DMATCR1]; - break; - case 2: - sar = sh4->m[SAR2]; - dar = sh4->m[DAR2]; - chcr = sh4->m[CHCR2]; - dmatcr = sh4->m[DMATCR2]; - break; - case 3: - sar = sh4->m[SAR3]; - dar = sh4->m[DAR3]; - chcr = sh4->m[CHCR3]; - dmatcr = sh4->m[DMATCR3]; - break; - default: - return; - } - if (chcr & sh4->m[DMAOR] & DMAOR_DME) - { - if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6)) - return; - if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->m[DMAOR] & (DMAOR_AE | DMAOR_NMIF))) - { - if (((chcr & CHCR_RS) >> 8) > 3) - sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr); - else if ((sh4->m[DMAOR] & DMAOR_DDT) == 0) - sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer - } - } - else - { - if (sh4->dma_timer_active[channel]) - { - logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel); - sh4->dma_timer[channel]->adjust(attotime::never, channel); - sh4->dma_timer_active[channel] = 0; - } - } -} - static void sh4_dmac_nmi(sh4_state *sh4) // manage dma when nmi gets asserted { -int s; + int s; - if (sh4->cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_dmac_nmi uses sh4->m[] with SH3\n"); - - sh4->m[DMAOR] |= DMAOR_NMIF; + sh4->SH4_DMAOR |= DMAOR_NMIF; for (s = 0;s < 4;s++) { if (sh4->dma_timer_active[s]) @@ -935,6 +666,7 @@ void sh4_handler_ipra_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) sh4_exception_recompute(sh4); } + WRITE32_HANDLER( sh4_internal_w ) { sh4_state *sh4 = get_safe_token(&space->device()); @@ -1089,50 +821,35 @@ WRITE32_HANDLER( sh4_internal_w ) sh4->exception_priority[SH4_INTC_GPOI] = INTPRI((sh4->m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI); sh4_exception_recompute(sh4); break; - - // DMA - case SAR0: - case SAR1: - case SAR2: - case SAR3: - case DAR0: - case DAR1: - case DAR2: - case DAR3: - case DMATCR0: - case DMATCR1: - case DMATCR2: - case DMATCR3: - break; - case CHCR0: - sh4_dmac_check(sh4, 0); - break; - case CHCR1: - sh4_dmac_check(sh4, 1); - break; - case CHCR2: - sh4_dmac_check(sh4, 2); - break; - case CHCR3: - sh4_dmac_check(sh4, 3); - break; - case DMAOR: - if ((sh4->m[DMAOR] & DMAOR_AE) && (~old & DMAOR_AE)) - sh4->m[DMAOR] &= ~DMAOR_AE; - if ((sh4->m[DMAOR] & DMAOR_NMIF) && (~old & DMAOR_NMIF)) - sh4->m[DMAOR] &= ~DMAOR_NMIF; - sh4_dmac_check(sh4, 0); - sh4_dmac_check(sh4, 1); - sh4_dmac_check(sh4, 2); - sh4_dmac_check(sh4, 3); - break; - - // Store Queues +/********************************************************************************************************************* + DMAC (DMA Controller) +*********************************************************************************************************************/ + case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break; + case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break; + case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break; + case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break; + case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break; + case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break; + case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break; + case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break; + case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break; + case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break; + case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break; + case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break; + case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break; + case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break; + case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break; + case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break; + case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data,mem_mask); break; +/********************************************************************************************************************* + Store Queues +*********************************************************************************************************************/ case QACR0: case QACR1: break; - - // I/O ports +/********************************************************************************************************************* + I/O +*********************************************************************************************************************/ case PCTRA: sh4->ioport16_pullup = 0; sh4->ioport16_direction = 0; @@ -1235,6 +952,26 @@ READ32_HANDLER( sh4_internal_r ) case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(sh4, mem_mask); // not supported case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(sh4, mem_mask); // not supported /********************************************************************************************************************* + DMAC (DMA Controller) +*********************************************************************************************************************/ + case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask); + case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask); + case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask); + case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask); + case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask); + case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask); + case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask); + case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask); + case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask); + case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask); + case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask); + case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask); + case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask); + case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask); + case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask); + case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask); + case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask); +/********************************************************************************************************************* I/O Ports *********************************************************************************************************************/ @@ -1491,270 +1228,6 @@ void sh4_common_init(device_t *device) sh4->m = auto_alloc_array(device->machine(), UINT32, 16384); } -// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu -int sh4_dma_data(device_t *device, struct sh4_device_dma *s) -{ - UINT32 pos, len, siz; - int channel = s->channel; - void *data = s->buffer; - - sh4_state *sh4 = get_safe_token(device); - - if (!sh4->dma_timer_active[channel]) - return 0; - - if (sh4->dma_mode[channel] == 2) - { - // device receives data - len = sh4->dma_count[channel]; - if (s->length < len) - len = s->length; - siz = sh4->dma_wordsize[channel]; - for (pos = 0;pos < len;pos++) { - switch (siz) - { - case 8: - if (sh4->dma_source_increment[channel] == 2) - sh4->dma_source[channel] -= 8; - *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7); - if (sh4->dma_source_increment[channel] == 1) - sh4->dma_source[channel] += 8; - break; - case 1: - if (sh4->dma_source_increment[channel] == 2) - sh4->dma_source[channel]--; - *(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]); - if (sh4->dma_source_increment[channel] == 1) - sh4->dma_source[channel]++; - break; - case 2: - if (sh4->dma_source_increment[channel] == 2) - sh4->dma_source[channel] -= 2; - *(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1); - if (sh4->dma_source_increment[channel] == 1) - sh4->dma_source[channel] += 2; - break; - case 4: - if (sh4->dma_source_increment[channel] == 2) - sh4->dma_source[channel] -= 4; - *(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3); - if (sh4->dma_source_increment[channel] == 1) - sh4->dma_source[channel] += 4; - break; - case 32: - if (sh4->dma_source_increment[channel] == 2) - sh4->dma_source[channel] -= 32; - *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31); - *((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8); - *((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16); - *((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24); - if (sh4->dma_source_increment[channel] == 1) - sh4->dma_source[channel] += 32; - break; - } - sh4->dma_count[channel]--; - } - if (sh4->dma_count[channel] == 0) // all data transferred ? - { - sh4->dma_timer[channel]->adjust(attotime::zero, channel); - return 2; - } - return 1; - } - else if (sh4->dma_mode[channel] == 3) - { - // device sends data - len = sh4->dma_count[channel]; - if (s->length < len) - len = s->length; - siz = sh4->dma_wordsize[channel]; - for (pos = 0;pos < len;pos++) { - switch (siz) - { - case 8: - if (sh4->dma_destination_increment[channel] == 2) - sh4->dma_destination[channel]-=8; - sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data); - if (sh4->dma_destination_increment[channel] == 1) - sh4->dma_destination[channel]+=8; - break; - case 1: - if (sh4->dma_destination_increment[channel] == 2) - sh4->dma_destination[channel]--; - sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data); - if (sh4->dma_destination_increment[channel] == 1) - sh4->dma_destination[channel]++; - break; - case 2: - if (sh4->dma_destination_increment[channel] == 2) - sh4->dma_destination[channel]-=2; - sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data); - if (sh4->dma_destination_increment[channel] == 1) - sh4->dma_destination[channel]+=2; - break; - case 4: - if (sh4->dma_destination_increment[channel] == 2) - sh4->dma_destination[channel]-=4; - sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data); - if (sh4->dma_destination_increment[channel] == 1) - sh4->dma_destination[channel]+=4; - break; - case 32: - if (sh4->dma_destination_increment[channel] == 2) - sh4->dma_destination[channel]-=32; - sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data); - sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1)); - sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2)); - sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3)); - if (sh4->dma_destination_increment[channel] == 1) - sh4->dma_destination[channel]+=32; - break; - } - sh4->dma_count[channel]--; - } - - if (sh4->dma_count[channel] == 0) // all data transferred ? - { - sh4->dma_timer[channel]->adjust(attotime::zero, channel); - return 2; - } - return 1; - } - else - return 0; -} - -// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu -void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s) -{ - sh4_state *sh4 = get_safe_token(device); - UINT32 chcr; - UINT32 *p32bits; - UINT64 *p32bytes; - UINT32 pos,len,siz; - - if (sh4->cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n"); - - if (sh4->dma_timer_active[s->channel]) - return; - if (s->mode >= 0) { - switch (s->channel) - { - case 0: - if (s->mode & 1) - s->source = sh4->m[SAR0]; - if (s->mode & 2) - sh4->m[SAR0] = s->source; - if (s->mode & 4) - s->destination = sh4->m[DAR0]; - if (s->mode & 8) - sh4->m[DAR0] = s->destination; - break; - case 1: - if (s->mode & 1) - s->source = sh4->m[SAR1]; - if (s->mode & 2) - sh4->m[SAR1] = s->source; - if (s->mode & 4) - s->destination = sh4->m[DAR1]; - if (s->mode & 8) - sh4->m[DAR1] = s->destination; - break; - case 2: - if (s->mode & 1) - s->source = sh4->m[SAR2]; - if (s->mode & 2) - sh4->m[SAR2] = s->source; - if (s->mode & 4) - s->destination = sh4->m[DAR2]; - if (s->mode & 8) - sh4->m[DAR2] = s->destination; - break; - case 3: - default: - if (s->mode & 1) - s->source = sh4->m[SAR3]; - if (s->mode & 2) - sh4->m[SAR3] = s->source; - if (s->mode & 4) - s->destination = sh4->m[DAR3]; - if (s->mode & 8) - sh4->m[DAR3] = s->destination; - break; - } - switch (s->channel) - { - case 0: - chcr = sh4->m[CHCR0]; - len = sh4->m[DMATCR0]; - break; - case 1: - chcr = sh4->m[CHCR1]; - len = sh4->m[DMATCR1]; - break; - case 2: - chcr = sh4->m[CHCR2]; - len = sh4->m[DMATCR2]; - break; - case 3: - default: - chcr = sh4->m[CHCR3]; - len = sh4->m[DMATCR3]; - break; - } - if ((s->direction) == 0) { - chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10); - } else { - chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8); - } - siz = dmasize[(chcr >> 4) & 7]; - if (siz && (s->size)) - if ((len * siz) != (s->length * s->size)) - return; - sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len); - } else { - if (s->size == 4) { - if ((s->direction) == 0) { - len = s->length; - p32bits = (UINT32 *)(s->buffer); - for (pos = 0;pos < len;pos++) { - *p32bits = sh4->program->read_dword(s->source); - p32bits++; - s->source = s->source + 4; - } - } else { - len = s->length; - p32bits = (UINT32 *)(s->buffer); - for (pos = 0;pos < len;pos++) { - sh4->program->write_dword(s->destination, *p32bits); - p32bits++; - s->destination = s->destination + 4; - } - } - } - if (s->size == 32) { - if ((s->direction) == 0) { - len = s->length * 4; - p32bytes = (UINT64 *)(s->buffer); - for (pos = 0;pos < len;pos++) { - *p32bytes = sh4->program->read_qword(s->source); - p32bytes++; - s->destination = s->destination + 8; - } - } else { - len = s->length * 4; - p32bytes = (UINT64 *)(s->buffer); - for (pos = 0;pos < len;pos++) { - sh4->program->write_qword(s->destination, *p32bytes); - p32bytes++; - s->destination = s->destination + 8; - } - } - } - } -} - UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address) { if (!sh4->sh4_mmu_enabled) diff --git a/src/emu/cpu/sh4/sh4comn.h b/src/emu/cpu/sh4/sh4comn.h index 76476a7202f..fd0faaa3b51 100644 --- a/src/emu/cpu/sh4/sh4comn.h +++ b/src/emu/cpu/sh4/sh4comn.h @@ -101,6 +101,29 @@ typedef struct UINT32 SH4_IPRC; + // DMAC regs + UINT32 SH4_SAR0; + UINT32 SH4_SAR1; + UINT32 SH4_SAR2; + UINT32 SH4_SAR3; + + UINT32 SH4_DAR0; + UINT32 SH4_DAR1; + UINT32 SH4_DAR2; + UINT32 SH4_DAR3; + + UINT32 SH4_CHCR0; + UINT32 SH4_CHCR1; + UINT32 SH4_CHCR2; + UINT32 SH4_CHCR3; + + UINT32 SH4_DMATCR0; + UINT32 SH4_DMATCR1; + UINT32 SH4_DMATCR2; + UINT32 SH4_DMATCR3; + + UINT32 SH4_DMAOR; + // sh3 internal UINT32 m_sh3internal_upper[0x3000/4]; diff --git a/src/emu/cpu/sh4/sh4dmac.c b/src/emu/cpu/sh4/sh4dmac.c new file mode 100644 index 00000000000..4649625e957 --- /dev/null +++ b/src/emu/cpu/sh4/sh4dmac.c @@ -0,0 +1,686 @@ +/* SHA3/4 DMA Controller */ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4dmac.h" + +static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 }; + +static const int sh3_dmasize[4] = { 1, 2, 4, 16 }; + +TIMER_CALLBACK( sh4_dmac_callback ) +{ + sh4_state *sh4 = (sh4_state *)ptr; + int channel = param; + + LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel)); + sh4->dma_timer_active[channel] = 0; + switch (channel) + { + case 0: + sh4->SH4_DMATCR0 = 0; + sh4->SH4_CHCR0 |= CHCR_TE; + if (sh4->SH4_CHCR0 & CHCR_IE) + sh4_exception_request(sh4, SH4_INTC_DMTE0); + break; + case 1: + sh4->SH4_DMATCR1 = 0; + sh4->SH4_CHCR1 |= CHCR_TE; + if (sh4->SH4_CHCR1 & CHCR_IE) + sh4_exception_request(sh4, SH4_INTC_DMTE1); + break; + case 2: + sh4->SH4_DMATCR2 = 0; + sh4->SH4_CHCR2 |= CHCR_TE; + if (sh4->SH4_CHCR2 & CHCR_IE) + sh4_exception_request(sh4, SH4_INTC_DMTE2); + break; + case 3: + sh4->SH4_DMATCR3 = 0; + sh4->SH4_CHCR3 |= CHCR_TE; + if (sh4->SH4_CHCR3 & CHCR_IE) + sh4_exception_request(sh4, SH4_INTC_DMTE3); + break; + } +} + +static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr) +{ + int incs, incd, size; + UINT32 src, dst, count; + + incd = (chcr & CHCR_DM) >> 14; + incs = (chcr & CHCR_SM) >> 12; + + if (sh4->cpu_type == CPU_TYPE_SH4) + { + size = dmasize[(chcr & CHCR_TS) >> 4]; + } + else + { + size = sh3_dmasize[(chcr >> 3) & 3]; + } + + if(incd == 3 || incs == 3) + { + logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); + return 0; + } + src = *sar; + dst = *dar; + count = *dmatcr; + if (!count) + count = 0x1000000; + + LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); + + if (timermode == 1) // timer actvated after a time based on the number of words to transfer + { + sh4->dma_timer_active[channel] = 1; + sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel); + } + else if (timermode == 2) // timer activated immediately + { + sh4->dma_timer_active[channel] = 1; + sh4->dma_timer[channel]->adjust(attotime::zero, channel); + } + + src &= AM; + dst &= AM; + + switch(size) + { + case 1: // 8 bit + for(;count > 0; count --) + { + if(incs == 2) + src --; + if(incd == 2) + dst --; + sh4->program->write_byte(dst, sh4->program->read_byte(src)); + if(incs == 1) + src ++; + if(incd == 1) + dst ++; + } + break; + case 2: // 16 bit + src &= ~1; + dst &= ~1; + for(;count > 0; count --) + { + if(incs == 2) + src -= 2; + if(incd == 2) + dst -= 2; + sh4->program->write_word(dst, sh4->program->read_word(src)); + if(incs == 1) + src += 2; + if(incd == 1) + dst += 2; + } + break; + case 8: // 64 bit + src &= ~7; + dst &= ~7; + for(;count > 0; count --) + { + if(incs == 2) + src -= 8; + if(incd == 2) + dst -= 8; + sh4->program->write_qword(dst, sh4->program->read_qword(src)); + if(incs == 1) + src += 8; + if(incd == 1) + dst += 8; + + } + break; + case 4: // 32 bit + src &= ~3; + dst &= ~3; + for(;count > 0; count --) + { + if(incs == 2) + src -= 4; + if(incd == 2) + dst -= 4; + sh4->program->write_dword(dst, sh4->program->read_dword(src)); + if(incs == 1) + src += 4; + if(incd == 1) + dst += 4; + + } + break; + case 32: + src &= ~31; + dst &= ~31; + for(;count > 0; count --) + { + if(incs == 2) + src -= 32; + if(incd == 2) + dst -= 32; + sh4->program->write_qword(dst, sh4->program->read_qword(src)); + sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8)); + sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16)); + sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24)); + if(incs == 1) + src += 32; + if(incd == 1) + dst += 32; + } + break; + } + *sar = (*sar & !AM) | src; + *dar = (*dar & !AM) | dst; + *dmatcr = count; + return 1; +} + +static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr) +{ + int incs, incd, size, mod; + UINT32 src, dst, count; + + incd = (chcr & CHCR_DM) >> 14; + incs = (chcr & CHCR_SM) >> 12; + + + if (sh4->cpu_type == CPU_TYPE_SH4) + { + size = dmasize[(chcr & CHCR_TS) >> 4]; + } + else + { + size = sh3_dmasize[(chcr >> 3) & 3]; + } + + mod = ((chcr & CHCR_RS) >> 8); + if (incd == 3 || incs == 3) + { + logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); + return 0; + } + src = *sar; + dst = *dar; + count = *dmatcr; + if (!count) + count = 0x1000000; + + LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); + + sh4->dma_timer_active[channel] = 1; + + src &= AM; + dst &= AM; + + // remember parameters + sh4->dma_source[channel]=src; + sh4->dma_destination[channel]=dst; + sh4->dma_count[channel]=count; + sh4->dma_wordsize[channel]=size; + sh4->dma_source_increment[channel]=incs; + sh4->dma_destination_increment[channel]=incd; + sh4->dma_mode[channel]=mod; + + // inform device its ready to transfer + sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16)); + return 1; +} + +static void sh4_dmac_check(sh4_state *sh4, int channel) +{ + UINT32 dmatcr, chcr, sar, dar; + + switch (channel) + { + case 0: + sar = sh4->SH4_SAR0; + dar = sh4->SH4_DAR0; + chcr = sh4->SH4_CHCR0; + dmatcr = sh4->SH4_DMATCR0; + break; + case 1: + sar = sh4->SH4_SAR1; + dar = sh4->SH4_DAR1; + chcr = sh4->SH4_CHCR1; + dmatcr = sh4->SH4_DMATCR1; + break; + case 2: + sar = sh4->SH4_SAR2; + dar = sh4->SH4_DAR2; + chcr = sh4->SH4_CHCR2; + dmatcr = sh4->SH4_DMATCR2; + break; + case 3: + sar = sh4->SH4_SAR3; + dar = sh4->SH4_DAR3; + chcr = sh4->SH4_CHCR3; + dmatcr = sh4->SH4_DMATCR3; + break; + default: + return; + } + if (chcr & sh4->SH4_DMAOR & DMAOR_DME) + { + if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6)) + return; + if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF))) + { + if (((chcr & CHCR_RS) >> 8) > 3) + sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr); + else if ((sh4->SH4_DMAOR & DMAOR_DDT) == 0) + sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer + } + } + else + { + if (sh4->dma_timer_active[channel]) + { + logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel); + sh4->dma_timer[channel]->adjust(attotime::never, channel); + sh4->dma_timer_active[channel] = 0; + } + } +} + + +// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu +int sh4_dma_data(device_t *device, struct sh4_device_dma *s) +{ + UINT32 pos, len, siz; + int channel = s->channel; + void *data = s->buffer; + + sh4_state *sh4 = get_safe_token(device); + + if (!sh4->dma_timer_active[channel]) + return 0; + + if (sh4->dma_mode[channel] == 2) + { + // device receives data + len = sh4->dma_count[channel]; + if (s->length < len) + len = s->length; + siz = sh4->dma_wordsize[channel]; + for (pos = 0;pos < len;pos++) { + switch (siz) + { + case 8: + if (sh4->dma_source_increment[channel] == 2) + sh4->dma_source[channel] -= 8; + *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7); + if (sh4->dma_source_increment[channel] == 1) + sh4->dma_source[channel] += 8; + break; + case 1: + if (sh4->dma_source_increment[channel] == 2) + sh4->dma_source[channel]--; + *(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]); + if (sh4->dma_source_increment[channel] == 1) + sh4->dma_source[channel]++; + break; + case 2: + if (sh4->dma_source_increment[channel] == 2) + sh4->dma_source[channel] -= 2; + *(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1); + if (sh4->dma_source_increment[channel] == 1) + sh4->dma_source[channel] += 2; + break; + case 4: + if (sh4->dma_source_increment[channel] == 2) + sh4->dma_source[channel] -= 4; + *(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3); + if (sh4->dma_source_increment[channel] == 1) + sh4->dma_source[channel] += 4; + break; + case 32: + if (sh4->dma_source_increment[channel] == 2) + sh4->dma_source[channel] -= 32; + *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31); + *((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8); + *((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16); + *((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24); + if (sh4->dma_source_increment[channel] == 1) + sh4->dma_source[channel] += 32; + break; + } + sh4->dma_count[channel]--; + } + if (sh4->dma_count[channel] == 0) // all data transferred ? + { + sh4->dma_timer[channel]->adjust(attotime::zero, channel); + return 2; + } + return 1; + } + else if (sh4->dma_mode[channel] == 3) + { + // device sends data + len = sh4->dma_count[channel]; + if (s->length < len) + len = s->length; + siz = sh4->dma_wordsize[channel]; + for (pos = 0;pos < len;pos++) { + switch (siz) + { + case 8: + if (sh4->dma_destination_increment[channel] == 2) + sh4->dma_destination[channel]-=8; + sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data); + if (sh4->dma_destination_increment[channel] == 1) + sh4->dma_destination[channel]+=8; + break; + case 1: + if (sh4->dma_destination_increment[channel] == 2) + sh4->dma_destination[channel]--; + sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data); + if (sh4->dma_destination_increment[channel] == 1) + sh4->dma_destination[channel]++; + break; + case 2: + if (sh4->dma_destination_increment[channel] == 2) + sh4->dma_destination[channel]-=2; + sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data); + if (sh4->dma_destination_increment[channel] == 1) + sh4->dma_destination[channel]+=2; + break; + case 4: + if (sh4->dma_destination_increment[channel] == 2) + sh4->dma_destination[channel]-=4; + sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data); + if (sh4->dma_destination_increment[channel] == 1) + sh4->dma_destination[channel]+=4; + break; + case 32: + if (sh4->dma_destination_increment[channel] == 2) + sh4->dma_destination[channel]-=32; + sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data); + sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1)); + sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2)); + sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3)); + if (sh4->dma_destination_increment[channel] == 1) + sh4->dma_destination[channel]+=32; + break; + } + sh4->dma_count[channel]--; + } + + if (sh4->dma_count[channel] == 0) // all data transferred ? + { + sh4->dma_timer[channel]->adjust(attotime::zero, channel); + return 2; + } + return 1; + } + else + return 0; +} + +// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu +void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s) +{ + sh4_state *sh4 = get_safe_token(device); + UINT32 chcr; + UINT32 *p32bits; + UINT64 *p32bytes; + UINT32 pos,len,siz; + + if (sh4->cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n"); + + if (sh4->dma_timer_active[s->channel]) + return; + if (s->mode >= 0) { + switch (s->channel) + { + case 0: + if (s->mode & 1) + s->source = sh4->SH4_SAR0; + if (s->mode & 2) + sh4->SH4_SAR0 = s->source; + if (s->mode & 4) + s->destination = sh4->SH4_DAR0; + if (s->mode & 8) + sh4->SH4_DAR0 = s->destination; + break; + case 1: + if (s->mode & 1) + s->source = sh4->SH4_SAR1; + if (s->mode & 2) + sh4->SH4_SAR1 = s->source; + if (s->mode & 4) + s->destination = sh4->SH4_DAR1; + if (s->mode & 8) + sh4->SH4_DAR1 = s->destination; + break; + case 2: + if (s->mode & 1) + s->source = sh4->SH4_SAR2; + if (s->mode & 2) + sh4->SH4_SAR2 = s->source; + if (s->mode & 4) + s->destination = sh4->SH4_DAR2; + if (s->mode & 8) + sh4->SH4_DAR2 = s->destination; + break; + case 3: + default: + if (s->mode & 1) + s->source = sh4->SH4_SAR3; + if (s->mode & 2) + sh4->SH4_SAR3 = s->source; + if (s->mode & 4) + s->destination = sh4->SH4_DAR3; + if (s->mode & 8) + sh4->SH4_DAR3 = s->destination; + break; + } + switch (s->channel) + { + case 0: + chcr = sh4->SH4_CHCR0; + len = sh4->SH4_DMATCR0; + break; + case 1: + chcr = sh4->SH4_CHCR1; + len = sh4->SH4_DMATCR1; + break; + case 2: + chcr = sh4->SH4_CHCR2; + len = sh4->SH4_DMATCR2; + break; + case 3: + default: + chcr = sh4->SH4_CHCR3; + len = sh4->SH4_DMATCR3; + break; + } + if ((s->direction) == 0) { + chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10); + } else { + chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8); + } + + + if (sh4->cpu_type == CPU_TYPE_SH4) + { + //siz = dmasize[(chcr & CHCR_TS) >> 4]; + siz = dmasize[(chcr >> 4) & 7]; + } + else + { + siz = sh3_dmasize[(chcr >> 3) & 3]; + } + + + if (siz && (s->size)) + if ((len * siz) != (s->length * s->size)) + return; + sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len); + } else { + if (s->size == 4) { + if ((s->direction) == 0) { + len = s->length; + p32bits = (UINT32 *)(s->buffer); + for (pos = 0;pos < len;pos++) { + *p32bits = sh4->program->read_dword(s->source); + p32bits++; + s->source = s->source + 4; + } + } else { + len = s->length; + p32bits = (UINT32 *)(s->buffer); + for (pos = 0;pos < len;pos++) { + sh4->program->write_dword(s->destination, *p32bits); + p32bits++; + s->destination = s->destination + 4; + } + } + } + if (s->size == 32) { + if ((s->direction) == 0) { + len = s->length * 4; + p32bytes = (UINT64 *)(s->buffer); + for (pos = 0;pos < len;pos++) { + *p32bytes = sh4->program->read_qword(s->source); + p32bytes++; + s->destination = s->destination + 8; + } + } else { + len = s->length * 4; + p32bytes = (UINT64 *)(s->buffer); + for (pos = 0;pos < len;pos++) { + sh4->program->write_qword(s->destination, *p32bytes); + p32bytes++; + s->destination = s->destination + 8; + } + } + } + } +} + + + void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_SAR0); +} + + void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_SAR1); +} + + void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_SAR2); +} + + void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_SAR3); +} + + void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DAR0); +} + + void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DAR1); +} + + void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DAR2); +} + + void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DAR3); +} + + void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DMATCR0); +} + + void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DMATCR1); +} + + void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DMATCR2); +} + + void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_DMATCR3); +} + + void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_CHCR0); + sh4_dmac_check(sh4, 0); +} + + void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_CHCR1); + sh4_dmac_check(sh4, 1); +} + + void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_CHCR2); + sh4_dmac_check(sh4, 2); +} + + void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_CHCR3); + sh4_dmac_check(sh4, 3); +} + + void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + UINT32 old = sh4->SH4_DMAOR; + COMBINE_DATA(&sh4->SH4_DMAOR); + + if ((sh4->SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE)) + sh4->SH4_DMAOR &= ~DMAOR_AE; + if ((sh4->SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF)) + sh4->SH4_DMAOR &= ~DMAOR_NMIF; + sh4_dmac_check(sh4, 0); + sh4_dmac_check(sh4, 1); + sh4_dmac_check(sh4, 2); + sh4_dmac_check(sh4, 3); +} + + UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR0; } + UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR1; } + UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR2; } + UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR3; } + UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR0; } + UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR1; } + UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR2; } + UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR3; } + UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR0; } + UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR1; } + UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR2; } + UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR3; } + UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR0; } + UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR1; } + UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR2; } + UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR3; } + UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMAOR; } diff --git a/src/emu/cpu/sh4/sh4dmac.h b/src/emu/cpu/sh4/sh4dmac.h new file mode 100644 index 00000000000..012ddcc21d2 --- /dev/null +++ b/src/emu/cpu/sh4/sh4dmac.h @@ -0,0 +1,63 @@ +/* SHA3/4 DMA Controller */ + +/* bit definitions */ +#define CHCR_SSA 0xe0000000 +#define CHCR_STC 0x10000000 +#define CHCR_DSA 0x0e000000 +#define CHCR_DTC 0x01000000 +#define CHCR_DS 0x00080000 +#define CHCR_RL 0x00040000 +#define CHCR_AM 0x00020000 +#define CHCR_AL 0x00010000 +#define CHCR_DM 0x0000c000 +#define CHCR_SM 0x00003000 +#define CHCR_RS 0x00000f00 +#define CHCR_TM 0x00000080 +#define CHCR_TS 0x00000070 +#define CHCR_IE 0x00000004 +#define CHCR_TE 0x00000002 +#define CHCR_DE 0x00000001 + +#define DMAOR_DDT 0x8000 +#define DMAOR_PR 0x0300 +#define DMAOR_COD 0x0010 +#define DMAOR_AE 0x0004 +#define DMAOR_NMIF 0x0002 +#define DMAOR_DME 0x0001 + +TIMER_CALLBACK( sh4_dmac_callback ); + +void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask); diff --git a/src/emu/cpu/sh4/sh4regs.h b/src/emu/cpu/sh4/sh4regs.h index 422d19cf056..c33dc0a67b4 100644 --- a/src/emu/cpu/sh4/sh4regs.h +++ b/src/emu/cpu/sh4/sh4regs.h @@ -49,23 +49,23 @@ #define GPIOIC 0x3012 /* FF800048 */ #define SDMR2 0x3200 /* FF900000 */ #define SDMR3 0x3280 /* FF940000 */ -#define SAR0 0x3400 /* FFA00000 */ -#define DAR0 0x3401 /* FFA00004 */ -#define DMATCR0 0x3402 /* FFA00008 */ -#define CHCR0 0x3403 /* FFA0000C */ -#define SAR1 0x3404 /* FFA00010 */ -#define DAR1 0x3405 /* FFA00014 */ -#define DMATCR1 0x3406 /* FFA00018 */ -#define CHCR1 0x3407 /* FFA0001C */ -#define SAR2 0x3408 /* FFA00020 */ -#define DAR2 0x3409 /* FFA00024 */ -#define DMATCR2 0x340A /* FFA00028 */ -#define CHCR2 0x340B /* FFA0002C */ -#define SAR3 0x340C /* FFA00030 */ -#define DAR3 0x340D /* FFA00034 */ -#define DMATCR3 0x340E /* FFA00038 */ -#define CHCR3 0x340F /* FFA0003C */ -#define DMAOR 0x3410 /* FFA00040 */ +#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */ +#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */ +#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */ +#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */ +#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */ +#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */ +#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */ +#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */ +#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */ +#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */ +#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */ +#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */ +#define SH4_SAR3_ADDR 0x340C /* FFA00030 */ +#define SH4_DAR3_ADDR 0x340D /* FFA00034 */ +#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */ +#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */ +#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */ #define SAR4 0x3414 /* FFA00050 */ #define DAR4 0x3415 /* FFA00054 */ #define DMATCR4 0x3416 /* FFA00058 */ @@ -158,30 +158,7 @@ #define SDINT 0x3E05 /* FFF00014 */ #define SIZEREGS 15878 -/* bit definitions */ -#define CHCR_SSA 0xe0000000 -#define CHCR_STC 0x10000000 -#define CHCR_DSA 0x0e000000 -#define CHCR_DTC 0x01000000 -#define CHCR_DS 0x00080000 -#define CHCR_RL 0x00040000 -#define CHCR_AM 0x00020000 -#define CHCR_AL 0x00010000 -#define CHCR_DM 0x0000c000 -#define CHCR_SM 0x00003000 -#define CHCR_RS 0x00000f00 -#define CHCR_TM 0x00000080 -#define CHCR_TS 0x00000070 -#define CHCR_IE 0x00000004 -#define CHCR_TE 0x00000002 -#define CHCR_DE 0x00000001 -#define DMAOR_DDT 0x8000 -#define DMAOR_PR 0x0300 -#define DMAOR_COD 0x0010 -#define DMAOR_AE 0x0004 -#define DMAOR_NMIF 0x0002 -#define DMAOR_DME 0x0001 #define MMUCR_LRUI 0xfc000000 #define MMUCR_URB 0x00fc0000 |