diff options
author | 2011-10-07 12:57:06 +0000 | |
---|---|---|
committer | 2011-10-07 12:57:06 +0000 | |
commit | 56e64fe500334c14aaaa5b417663dbd77023a41c (patch) | |
tree | b1319de1aeea1cd96f2afdaae2b4331aa74c252c /src/emu | |
parent | bc30cc554d6c06c637544cadce4d63d1d2a34d47 (diff) |
Reusing the SH4 timer code for the SH3 after a bit of refactoring by Haze (no whatsnew)
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/cpu/cpu.mak | 11 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh3comn.c | 77 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh3comn.h | 17 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4.c | 5 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4comn.c | 292 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4regs.h | 24 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4tmu.c | 315 | ||||
-rw-r--r-- | src/emu/cpu/sh4/sh4tmu.h | 30 |
8 files changed, 486 insertions, 285 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 0220c3e9d19..9b83197d3b5 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 +CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o DASMOBJS += $(CPUOBJ)/sh4/sh4dasm.o endif @@ -550,6 +550,15 @@ $(CPUOBJ)/sh4/sh4comn.o: $(CPUSRC)/sh4/sh4comn.c \ $(CPUOBJ)/sh4/sh3comn.o: $(CPUSRC)/sh4/sh3comn.c \ $(CPUSRC)/sh4/sh3comn.h \ +$(CPUOBJ)/sh4/sh4tmu.o: $(CPUSRC)/sh4/sh4tmu.c \ + $(CPUSRC)/sh4/sh4tmu.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 166bfba2978..1a57ba1caeb 100644 --- a/src/emu/cpu/sh4/sh3comn.c +++ b/src/emu/cpu/sh4/sh3comn.c @@ -5,32 +5,99 @@ #include "sh4.h" #include "sh4comn.h" #include "sh3comn.h" - +#include "sh4tmu.h" /* High internal area (ffffxxxx) */ WRITE32_HANDLER( sh3_internal_high_w ) { sh4_state *sh4 = get_safe_token(&space->device()); + COMBINE_DATA(&sh4->m_sh3internal_upper[offset]); + + switch (offset) + { + case SH3_TOCR_TSTR_ADDR: + logerror("'%s' (%08x): TMU internal write to %08x = %08x & %08x (SH3_TOCR_TSTR_ADDR)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + if (mem_mask&0xff000000) + { + sh4_handle_tocr_addr_w(sh4, (data>>24)&0xffff, (mem_mask>>24)&0xff); + } + if (mem_mask&0x0000ff00) + { + sh4_handle_tstr_addr_w(sh4, (data>>8)&0xff, (mem_mask>>8)&0xff); + } + if (mem_mask&0x00ff00ff) + { + fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (write)\n"); + } + break; + case SH3_TCOR0_ADDR: sh4_handle_tcor0_addr_w(sh4, data, mem_mask);break; + case SH3_TCOR1_ADDR: sh4_handle_tcor1_addr_w(sh4, data, mem_mask);break; + case SH3_TCOR2_ADDR: sh4_handle_tcor2_addr_w(sh4, data, mem_mask);break; + case SH3_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(sh4, data, mem_mask);break; + case SH3_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(sh4, data, mem_mask);break; + case SH3_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(sh4, data, mem_mask);break; + case SH3_TCR0_ADDR: sh4_handle_tcr0_addr_w(sh4, data, mem_mask);break; + case SH3_TCR1_ADDR: sh4_handle_tcr1_addr_w(sh4, data, mem_mask);break; + case SH3_TCR2_ADDR: sh4_handle_tcr2_addr_w(sh4, data, mem_mask);break; + case SH3_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(sh4,data, mem_mask);break; + + default: + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (unk)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + break; + + } - COMBINE_DATA(&sh4->m_sh3internal_upper[offset]); + + + } READ32_HANDLER( sh3_internal_high_r ) { sh4_state *sh4 = get_safe_token(&space->device()); + UINT32 ret = 0; + switch (offset) { - case SH3_TRA: + case SH3_TOCR_TSTR_ADDR: + + if (mem_mask&0xff00000) + { + ret |= (sh4_handle_tocr_addr_r(sh4, mem_mask)&0xff)<<24; + } + if (mem_mask&0x0000ff00) + { + ret |= (sh4_handle_tstr_addr_r(sh4, mem_mask)&0xff)<<8; + } + if (mem_mask&0x00ff00ff) + { + fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (read)\n"); + } + return ret; + case SH3_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(sh4, mem_mask); + case SH3_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(sh4, mem_mask); + case SH3_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(sh4, mem_mask); + case SH3_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(sh4, mem_mask); + case SH3_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(sh4, mem_mask); + case SH3_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(sh4, mem_mask); + case SH3_TCR0_ADDR: return sh4_handle_tcr0_addr_r(sh4, mem_mask); + case SH3_TCR1_ADDR: return sh4_handle_tcr1_addr_r(sh4, mem_mask); + case SH3_TCR2_ADDR: return sh4_handle_tcr2_addr_r(sh4, mem_mask); + case SH3_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(sh4, mem_mask); + + + case SH3_TRA_ADDR: logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 TRA - %08x)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, sh4->m_sh3internal_upper[offset]); return sh4->m_sh3internal_upper[offset]; - case SH3_EXPEVT: + case SH3_EXPEVT_ADDR: logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 EXPEVT - %08x)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, sh4->m_sh3internal_upper[offset]); return sh4->m_sh3internal_upper[offset]; - case SH3_INTEVT: + case SH3_INTEVT_ADDR: logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 INTEVT - %08x)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, sh4->m_sh3internal_upper[offset]); + fatalerror("INTEVT unsupported on SH3\n"); return sh4->m_sh3internal_upper[offset]; diff --git a/src/emu/cpu/sh4/sh3comn.h b/src/emu/cpu/sh4/sh3comn.h index 972f84af32a..51f5b616b48 100644 --- a/src/emu/cpu/sh4/sh3comn.h +++ b/src/emu/cpu/sh4/sh3comn.h @@ -24,9 +24,20 @@ #define SH3_UPPER_REGBASE (0xffffd000) #define SH3_UPPER_REGEND (0xffffffff) -#define SH3_TRA ((0xffffffd0 - SH3_UPPER_REGBASE)/4) -#define SH3_EXPEVT ((0xffffffd4 - SH3_UPPER_REGBASE)/4) -#define SH3_INTEVT ((0xffffffd8 - SH3_UPPER_REGBASE)/4) +#define SH3_TOCR_TSTR_ADDR ((0xfffffe90 - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR0_ADDR ((0xfffffe94 - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT0_ADDR ((0xfffffe98 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR0_ADDR ((0xfffffe9c - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR1_ADDR ((0xfffffea0 - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT1_ADDR ((0xfffffea4 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR1_ADDR ((0xfffffea8 - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR2_ADDR ((0xfffffeac - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT2_ADDR ((0xfffffeb0 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR2_ADDR ((0xfffffeb4 - SH3_UPPER_REGBASE)/4) +#define SH3_TCPR2_ADDR ((0xfffffeb8 - SH3_UPPER_REGBASE)/4) +#define SH3_TRA_ADDR ((0xffffffd0 - SH3_UPPER_REGBASE)/4) +#define SH3_EXPEVT_ADDR ((0xffffffd4 - SH3_UPPER_REGBASE)/4) +#define SH3_INTEVT_ADDR ((0xffffffd8 - SH3_UPPER_REGBASE)/4) #endif /* __SH3COMN_H__ */ diff --git a/src/emu/cpu/sh4/sh4.c b/src/emu/cpu/sh4/sh4.c index a8af40e9fb0..210c2dbd5e9 100644 --- a/src/emu/cpu/sh4/sh4.c +++ b/src/emu/cpu/sh4/sh4.c @@ -28,6 +28,7 @@ #include "sh4regs.h" #include "sh4comn.h" #include "sh3comn.h" +#include "sh4tmu.h" #ifndef USE_SH4DRC @@ -1716,7 +1717,7 @@ INLINE void TRAPA(sh4_state *sh4, UINT32 i) } else /* SH3 */ { - sh4->m_sh3internal_upper[SH3_TRA] = imm << 2; + sh4->m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; } @@ -1739,7 +1740,7 @@ INLINE void TRAPA(sh4_state *sh4, UINT32 i) } else /* SH3 */ { - sh4->m_sh3internal_upper[SH3_EXPEVT] = 0x00000160; + sh4->m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; } sh4->pc = sh4->vbr + 0x00000100; diff --git a/src/emu/cpu/sh4/sh4comn.c b/src/emu/cpu/sh4/sh4comn.c index 0546bed1196..2b483f8d289 100644 --- a/src/emu/cpu/sh4/sh4comn.c +++ b/src/emu/cpu/sh4/sh4comn.c @@ -12,8 +12,9 @@ #include "sh4regs.h" #include "sh4comn.h" #include "sh3comn.h" +#include "sh4tmu.h" + -static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 }; 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 }; @@ -337,7 +338,7 @@ void sh4_exception(sh4_state *sh4, const char *message, int exception) // handle //printf("exception %04x\n", exception); //sh4->m_sh3internal_lower[INTEVT2] = sh3_intevt2_exception_codes[exception]; sh4->m_sh3internal_lower[INTEVT2] = callbackval; - sh4->m_sh3internal_upper[SH3_EXPEVT] = exception_codes[exception]; + sh4->m_sh3internal_upper[SH3_EXPEVT_ADDR] = exception_codes[exception]; LOG(("SH-3 '%s' interrupt exception #%d after [%s]\n", sh4->device->tag(), exception, message)); @@ -366,6 +367,7 @@ void sh4_exception(sh4_state *sh4, const char *message, int exception) // handle if(sh4->sleep_mode == 1) { sh4->sleep_mode = 2; } } + static UINT32 compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor) { // elapsed:total = x : ticks @@ -391,51 +393,6 @@ UINT32 ticks; sh4->refresh_timer_base = sh4->m[RTCNT]; } -/*------------------------------------------------- - sh4_scale_up_mame_time - multiply a attotime by - a (constant+1) where 0 <= constant < 2^32 --------------------------------------------------*/ - -INLINE attotime sh4_scale_up_mame_time(attotime _time1, UINT32 factor1) -{ - return _time1 * factor1 + _time1; -} - -static UINT32 compute_ticks_timer(emu_timer *timer, int hertz, int divisor) -{ - double ret; - - ret=((timer->remaining().as_double() * (double)hertz) / (double)divisor) - 1; - return (UINT32)ret; -} - -static void sh4_timer_recompute(sh4_state *sh4, int which) -{ - double ticks; - - UINT32 tcnt = 0; - UINT32 tcr = 0; - switch (which) - { - case 0: - tcr = sh4->SH4_TCR0; - tcnt = sh4->SH4_TCNT0; - break; - - case 1: - tcr = sh4->SH4_TCR1; - tcnt = sh4->SH4_TCNT1; - break; - - case 2: - tcr = sh4->SH4_TCR2; - tcnt = sh4->SH4_TCNT2; - break; - } - - ticks = tcnt; - sh4->timer[which]->adjust(sh4_scale_up_mame_time(attotime::from_hz(sh4->pm_clock) * tcnt_div[tcr & 7], ticks), which); -} static TIMER_CALLBACK( sh4_refresh_timer_callback ) { @@ -574,66 +531,6 @@ static TIMER_CALLBACK( sh4_rtc_timer_callback ) } } -static TIMER_CALLBACK( sh4_timer_callback ) -{ - sh4_state *sh4 = (sh4_state *)ptr; - int which = param; - - switch (which) - { - case 0: - sh4->SH4_TCNT0 = sh4->SH4_TCOR0; - break; - - case 1: - sh4->SH4_TCNT1 = sh4->SH4_TCOR1; - break; - - case 2: - sh4->SH4_TCNT2 = sh4->SH4_TCOR2; - break; - - } - - sh4_timer_recompute(sh4, which); - - switch (which) - { - case 0: - sh4->SH4_TCR0 |= 0x100; - break; - - case 1: - sh4->SH4_TCR1 |= 0x100; - break; - - case 2: - sh4->SH4_TCR2 |= 0x100; - break; - - } - - switch (which) - { - case 0: - if (sh4->SH4_TCR0 & 0x20) - sh4_exception_request(sh4, SH4_INTC_TUNI0); - break; - - case 1: - if (sh4->SH4_TCR1 & 0x20) - sh4_exception_request(sh4, SH4_INTC_TUNI1); - break; - - case 2: - if (sh4->SH4_TCR2 & 0x20) - sh4_exception_request(sh4, SH4_INTC_TUNI2); - break; - - } - - -} static TIMER_CALLBACK( sh4_dmac_callback ) { @@ -920,6 +817,8 @@ int s; } } + + WRITE32_HANDLER( sh4_internal_w ) { sh4_state *sh4 = get_safe_token(&space->device()); @@ -932,7 +831,6 @@ WRITE32_HANDLER( sh4_internal_w ) UINT32 old = sh4->m[offset]; COMBINE_DATA(sh4->m+offset); - UINT32 old2 = 0; // printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask); @@ -1032,113 +930,18 @@ WRITE32_HANDLER( sh4_internal_w ) /********************************************************************************************************************* TMU (Timer Unit) *********************************************************************************************************************/ - case TSTR: - old2 = sh4->SH4_TSTR; - COMBINE_DATA(&sh4->SH4_TSTR); - - if (old2 & 1) - sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); - if ((sh4->SH4_TSTR & 1) == 0) { - sh4->timer[0]->adjust(attotime::never); - } else - sh4_timer_recompute(sh4, 0); - - if (old2 & 2) - sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); - if ((sh4->SH4_TSTR & 2) == 0) { - sh4->timer[1]->adjust(attotime::never); - } else - sh4_timer_recompute(sh4, 1); - - if (old2 & 4) - sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); - if ((sh4->SH4_TSTR & 4) == 0) { - sh4->timer[2]->adjust(attotime::never); - } else - sh4_timer_recompute(sh4, 2); - break; - - case TCR0: - old2 = sh4->SH4_TCR0; - COMBINE_DATA(&sh4->SH4_TCR0); - if (sh4->SH4_TSTR & 1) - { - sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(sh4, 0); - } - if (!(sh4->SH4_TCR0 & 0x20) || !(sh4->SH4_TCR0 & 0x100)) - sh4_exception_unrequest(sh4, SH4_INTC_TUNI0); - break; - case TCR1: - old2 = sh4->SH4_TCR1; - COMBINE_DATA(&sh4->SH4_TCR1); - if (sh4->SH4_TSTR & 2) - { - sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(sh4, 1); - } - if (!(sh4->SH4_TCR1 & 0x20) || !(sh4->SH4_TCR1 & 0x100)) - sh4_exception_unrequest(sh4, SH4_INTC_TUNI1); - break; - case TCR2: - old2 = sh4->SH4_TCR2; - COMBINE_DATA(&sh4->SH4_TCR2); - if (sh4->SH4_TSTR & 4) - { - sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(sh4, 2); - } - if (!(sh4->SH4_TCR2 & 0x20) || !(sh4->SH4_TCR2 & 0x100)) - sh4_exception_unrequest(sh4, SH4_INTC_TUNI2); - break; - - case TCOR0: - COMBINE_DATA(&sh4->SH4_TCOR0); - if (sh4->SH4_TSTR & 1) - { - sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); - sh4_timer_recompute(sh4, 0); - } - break; - case TCNT0: - COMBINE_DATA(&sh4->SH4_TCNT0); - if (sh4->SH4_TSTR & 1) - sh4_timer_recompute(sh4, 0); - break; - case TCOR1: - COMBINE_DATA(&sh4->SH4_TCOR1); - if (sh4->SH4_TSTR & 2) - { - sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); - sh4_timer_recompute(sh4, 1); - } - break; - case TCNT1: - COMBINE_DATA(&sh4->SH4_TCNT1); - if (sh4->SH4_TSTR & 2) - sh4_timer_recompute(sh4, 1); - break; - case TCOR2: - COMBINE_DATA(&sh4->SH4_TCOR2); - if (sh4->SH4_TSTR & 4) - { - sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); - sh4_timer_recompute(sh4, 2); - } - break; - case TCNT2: - COMBINE_DATA(&sh4->SH4_TCNT2); - if (sh4->SH4_TSTR & 4) - sh4_timer_recompute(sh4, 2); - break; - - case TOCR: // not supported - COMBINE_DATA(&sh4->SH4_TOCR); - break; - - case TCPR2: // not supported - COMBINE_DATA(&sh4->SH4_TCPR2); - break; + case SH4_TSTR_ADDR: sh4_handle_tstr_addr_w(sh4,data,mem_mask); break; + case SH4_TCR0_ADDR: sh4_handle_tcr0_addr_w(sh4,data,mem_mask); break; + case SH4_TCR1_ADDR: sh4_handle_tcr1_addr_w(sh4,data,mem_mask); break; + case SH4_TCR2_ADDR: sh4_handle_tcr2_addr_w(sh4,data,mem_mask); break; + case SH4_TCOR0_ADDR: sh4_handle_tcor0_addr_w(sh4,data,mem_mask); break; + case SH4_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(sh4,data,mem_mask); break; + case SH4_TCOR1_ADDR: sh4_handle_tcor1_addr_w(sh4,data,mem_mask); break; + case SH4_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(sh4,data,mem_mask); break; + case SH4_TCOR2_ADDR: sh4_handle_tcor2_addr_w(sh4,data,mem_mask); break; + case SH4_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(sh4,data,mem_mask); break; + case SH4_TOCR_ADDR: sh4_handle_tocr_addr_w(sh4,data,mem_mask); break; // not supported + case SH4_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(sh4,data,mem_mask); break; // not supported /********************************************************************************************************************* INTC (Interrupt Controller) *********************************************************************************************************************/ @@ -1306,53 +1109,18 @@ READ32_HANDLER( sh4_internal_r ) /********************************************************************************************************************* TMU (Timer Unit) *********************************************************************************************************************/ - - case TSTR: - return sh4->SH4_TSTR; - - case TCR0: - return sh4->SH4_TCR0; - - case TCR1: - return sh4->SH4_TCR1; - - case TCR2: - return sh4->SH4_TCR2; - - case TCNT0: - if (sh4->SH4_TSTR & 1) - return compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); - else - return sh4->SH4_TCNT0; - break; - case TCNT1: - if (sh4->SH4_TSTR & 2) - return compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); - else - return sh4->SH4_TCNT1; - break; - case TCNT2: - if (sh4->SH4_TSTR & 4) - return compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); - else - return sh4->SH4_TCNT2; - break; - - case TCOR0: - return sh4->SH4_TCOR0; - - case TCOR1: - return sh4->SH4_TCOR1; - - case TCOR2: - return sh4->SH4_TCOR2; - - case TOCR: // not supported - return sh4->SH4_TOCR; - - case TCPR2: // not supported - return sh4->SH4_TCPR2; - + case SH4_TSTR_ADDR: return sh4_handle_tstr_addr_r(sh4, mem_mask); + case SH4_TCR0_ADDR: return sh4_handle_tcr0_addr_r(sh4, mem_mask); + case SH4_TCR1_ADDR: return sh4_handle_tcr1_addr_r(sh4, mem_mask); + case SH4_TCR2_ADDR: return sh4_handle_tcr2_addr_r(sh4, mem_mask); + case SH4_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(sh4, mem_mask); + case SH4_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(sh4, mem_mask); + case SH4_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(sh4, mem_mask); + case SH4_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(sh4, mem_mask); + case SH4_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(sh4, mem_mask); + case SH4_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(sh4, mem_mask); + 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 /********************************************************************************************************************* I/O Ports *********************************************************************************************************************/ diff --git a/src/emu/cpu/sh4/sh4regs.h b/src/emu/cpu/sh4/sh4regs.h index a8ef7066798..422d19cf056 100644 --- a/src/emu/cpu/sh4/sh4regs.h +++ b/src/emu/cpu/sh4/sh4regs.h @@ -123,18 +123,18 @@ #define TCOR4 0x205 /* FE100014 */ #define TCNT4 0x206 /* FE100018 */ #define TCR4 0x207 /* FE10001C */ -#define TOCR 0x3B00 /* FFD80000 */ -#define TSTR 0x3B01 /* FFD80004 */ -#define TCOR0 0x3B02 /* FFD80008 */ -#define TCNT0 0x3B03 /* FFD8000C */ -#define TCR0 0x3B04 /* FFD80010 */ -#define TCOR1 0x3B05 /* FFD80014 */ -#define TCNT1 0x3B06 /* FFD80018 */ -#define TCR1 0x3B07 /* FFD8001C */ -#define TCOR2 0x3B08 /* FFD80020 */ -#define TCNT2 0x3B09 /* FFD80024 */ -#define TCR2 0x3B0A /* FFD80028 */ -#define TCPR2 0x3B0B /* FFD8002C */ +#define SH4_TOCR_ADDR 0x3B00 /* FFD80000 */ +#define SH4_TSTR_ADDR 0x3B01 /* FFD80004 */ +#define SH4_TCOR0_ADDR 0x3B02 /* FFD80008 */ +#define SH4_TCNT0_ADDR 0x3B03 /* FFD8000C */ +#define SH4_TCR0_ADDR 0x3B04 /* FFD80010 */ +#define SH4_TCOR1_ADDR 0x3B05 /* FFD80014 */ +#define SH4_TCNT1_ADDR 0x3B06 /* FFD80018 */ +#define SH4_TCR1_ADDR 0x3B07 /* FFD8001C */ +#define SH4_TCOR2_ADDR 0x3B08 /* FFD80020 */ +#define SH4_TCNT2_ADDR 0x3B09 /* FFD80024 */ +#define SH4_TCR2_ADDR 0x3B0A /* FFD80028 */ +#define SH4_TCPR2_ADDR 0x3B0B /* FFD8002C */ #define SCSMR1 0x3C00 /* FFE00000 */ #define SCBRR1 0x3C01 /* FFE00004 */ #define SCSCR1 0x3C02 /* FFE00008 */ diff --git a/src/emu/cpu/sh4/sh4tmu.c b/src/emu/cpu/sh4/sh4tmu.c new file mode 100644 index 00000000000..41c62f50eae --- /dev/null +++ b/src/emu/cpu/sh4/sh4tmu.c @@ -0,0 +1,315 @@ +/* SH3/4 Timer Unit */ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" + +static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 }; + +/*------------------------------------------------- + sh4_scale_up_mame_time - multiply a attotime by + a (constant+1) where 0 <= constant < 2^32 +-------------------------------------------------*/ + +INLINE attotime sh4_scale_up_mame_time(attotime _time1, UINT32 factor1) +{ + return _time1 * factor1 + _time1; +} + +static UINT32 compute_ticks_timer(emu_timer *timer, int hertz, int divisor) +{ + double ret; + + ret=((timer->remaining().as_double() * (double)hertz) / (double)divisor) - 1; + return (UINT32)ret; +} + +static void sh4_timer_recompute(sh4_state *sh4, int which) +{ + double ticks; + + UINT32 tcnt = 0; + UINT32 tcr = 0; + switch (which) + { + case 0: + tcr = sh4->SH4_TCR0; + tcnt = sh4->SH4_TCNT0; + break; + + case 1: + tcr = sh4->SH4_TCR1; + tcnt = sh4->SH4_TCNT1; + break; + + case 2: + tcr = sh4->SH4_TCR2; + tcnt = sh4->SH4_TCNT2; + break; + } + + ticks = tcnt; + sh4->timer[which]->adjust(sh4_scale_up_mame_time(attotime::from_hz(sh4->pm_clock) * tcnt_div[tcr & 7], ticks), which); +} + + +TIMER_CALLBACK( sh4_timer_callback ) +{ + sh4_state *sh4 = (sh4_state *)ptr; + int which = param; + + switch (which) + { + case 0: + sh4->SH4_TCNT0 = sh4->SH4_TCOR0; + break; + + case 1: + sh4->SH4_TCNT1 = sh4->SH4_TCOR1; + break; + + case 2: + sh4->SH4_TCNT2 = sh4->SH4_TCOR2; + break; + + } + + sh4_timer_recompute(sh4, which); + + switch (which) + { + case 0: + sh4->SH4_TCR0 |= 0x100; + break; + + case 1: + sh4->SH4_TCR1 |= 0x100; + break; + + case 2: + sh4->SH4_TCR2 |= 0x100; + break; + + } + + switch (which) + { + case 0: + if (sh4->SH4_TCR0 & 0x20) + sh4_exception_request(sh4, SH4_INTC_TUNI0); + break; + + case 1: + if (sh4->SH4_TCR1 & 0x20) + sh4_exception_request(sh4, SH4_INTC_TUNI1); + break; + + case 2: + if (sh4->SH4_TCR2 & 0x20) + sh4_exception_request(sh4, SH4_INTC_TUNI2); + break; + + } +} + + +UINT32 sh4_handle_tcnt0_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + if (sh4->SH4_TSTR & 1) + return compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); + else + return sh4->SH4_TCNT0; +} + +UINT32 sh4_handle_tcnt1_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + if (sh4->SH4_TSTR & 2) + return compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); + else + return sh4->SH4_TCNT1; +} + +UINT32 sh4_handle_tcnt2_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + if (sh4->SH4_TSTR & 4) + return compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); + else + return sh4->SH4_TCNT2; +} + +UINT32 sh4_handle_tcor0_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCOR0; +} + +UINT32 sh4_handle_tcor1_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCOR1; +} + +UINT32 sh4_handle_tcor2_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCOR2; +} + +UINT32 sh4_handle_tcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCR0; +} + +UINT32 sh4_handle_tcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCR1; +} + +UINT32 sh4_handle_tcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCR2; +} + +UINT32 sh4_handle_tstr_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TSTR; +} + +UINT32 sh4_handle_tocr_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TOCR; +} + +UINT32 sh4_handle_tcpr2_addr_r(sh4_state *sh4, UINT32 mem_mask) +{ + return sh4->SH4_TCPR2; +} + + +void sh4_handle_tstr_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + UINT32 old2 = sh4->SH4_TSTR; + COMBINE_DATA(&sh4->SH4_TSTR); + + if (old2 & 1) + sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); + if ((sh4->SH4_TSTR & 1) == 0) { + sh4->timer[0]->adjust(attotime::never); + } else + sh4_timer_recompute(sh4, 0); + + if (old2 & 2) + sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); + if ((sh4->SH4_TSTR & 2) == 0) { + sh4->timer[1]->adjust(attotime::never); + } else + sh4_timer_recompute(sh4, 1); + + if (old2 & 4) + sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); + if ((sh4->SH4_TSTR & 4) == 0) { + sh4->timer[2]->adjust(attotime::never); + } else + sh4_timer_recompute(sh4, 2); +} + +void sh4_handle_tcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + UINT32 old2 = sh4->SH4_TCR0; + COMBINE_DATA(&sh4->SH4_TCR0); + if (sh4->SH4_TSTR & 1) + { + sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(sh4, 0); + } + if (!(sh4->SH4_TCR0 & 0x20) || !(sh4->SH4_TCR0 & 0x100)) + sh4_exception_unrequest(sh4, SH4_INTC_TUNI0); +} + +void sh4_handle_tcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + UINT32 old2 = sh4->SH4_TCR1; + COMBINE_DATA(&sh4->SH4_TCR1); + if (sh4->SH4_TSTR & 2) + { + sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(sh4, 1); + } + if (!(sh4->SH4_TCR1 & 0x20) || !(sh4->SH4_TCR1 & 0x100)) + sh4_exception_unrequest(sh4, SH4_INTC_TUNI1); +} + +void sh4_handle_tcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + UINT32 old2 = sh4->SH4_TCR2; + COMBINE_DATA(&sh4->SH4_TCR2); + if (sh4->SH4_TSTR & 4) + { + sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(sh4, 2); + } + if (!(sh4->SH4_TCR2 & 0x20) || !(sh4->SH4_TCR2 & 0x100)) + sh4_exception_unrequest(sh4, SH4_INTC_TUNI2); +} + +void sh4_handle_tcor0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCOR0); + if (sh4->SH4_TSTR & 1) + { + sh4->SH4_TCNT0 = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->SH4_TCR0 & 7]); + sh4_timer_recompute(sh4, 0); + } +} + +void sh4_handle_tcor1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCOR1); + if (sh4->SH4_TSTR & 2) + { + sh4->SH4_TCNT1 = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->SH4_TCR1 & 7]); + sh4_timer_recompute(sh4, 1); + } +} + +void sh4_handle_tcor2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCOR2); + if (sh4->SH4_TSTR & 4) + { + sh4->SH4_TCNT2 = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->SH4_TCR2 & 7]); + sh4_timer_recompute(sh4, 2); + } +} + +void sh4_handle_tcnt0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCNT0); + if (sh4->SH4_TSTR & 1) + sh4_timer_recompute(sh4, 0); +} + +void sh4_handle_tcnt1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCNT1); + if (sh4->SH4_TSTR & 2) + sh4_timer_recompute(sh4, 1); +} + +void sh4_handle_tcnt2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCNT2); + if (sh4->SH4_TSTR & 4) + sh4_timer_recompute(sh4, 2); +} + +void sh4_handle_tocr_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TOCR); +} + +void sh4_handle_tcpr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&sh4->SH4_TCPR2); +} + diff --git a/src/emu/cpu/sh4/sh4tmu.h b/src/emu/cpu/sh4/sh4tmu.h new file mode 100644 index 00000000000..7829b85a52e --- /dev/null +++ b/src/emu/cpu/sh4/sh4tmu.h @@ -0,0 +1,30 @@ +/* SH3/4 Timer Unit */ + +TIMER_CALLBACK( sh4_timer_callback ); + +UINT32 sh4_handle_tcnt0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcnt1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcnt2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcor0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcor1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcor2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcr0_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcr1_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcr2_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tstr_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tocr_addr_r(sh4_state *sh4, UINT32 mem_mask); +UINT32 sh4_handle_tcpr2_addr_r(sh4_state *sh4, UINT32 mem_mask); + +void sh4_handle_tstr_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcor0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcor1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcor2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcnt0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcnt1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcnt2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tocr_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); +void sh4_handle_tcpr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask); + |