filename | src/sh4/timer.c |
changeset | 1124:aacaae9812ea |
prev | 975:007bf7eb944f |
next | 1127:4b8194e3974c |
author | nkeynes |
date | Mon Sep 13 10:13:42 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Implement shadow-execution 'core' to run translator + interpreter side by side (for testing) |
file | annotate | diff | log | raw |
1.1 --- a/src/sh4/timer.c Mon Jan 26 07:26:24 2009 +00001.2 +++ b/src/sh4/timer.c Mon Sep 13 10:13:42 2010 +10001.3 @@ -42,7 +42,7 @@1.5 uint32_t sh4_cpu_period = 1000 / SH4_BASE_RATE; /* in nanoseconds */1.6 uint32_t sh4_bus_period = 2* 1000 / SH4_BASE_RATE;1.7 -uint32_t sh4_peripheral_period = 4 * 2000 / SH4_BASE_RATE;1.8 +uint32_t sh4_peripheral_period = 4 * 1000 / SH4_BASE_RATE;1.10 MMIO_REGION_READ_FN( CPG, reg )1.11 {1.12 @@ -112,13 +112,29 @@1.14 /********************************** TMU *************************************/1.16 +#define TCR_ICPF 0x02001.17 +#define TCR_UNF 0x01001.18 +#define TCR_UNIE 0x00201.19 +1.20 +#define TCR_IRQ_ACTIVE (TCR_UNF|TCR_UNIE)1.21 +1.22 #define TMU_IS_RUNNING(timer) (MMIO_READ(TMU,TSTR) & (1<<timer))1.24 +struct TMU_timer {1.25 + uint32_t timer_period;1.26 + uint32_t timer_remainder; /* left-over cycles from last count */1.27 + uint32_t timer_run; /* cycles already run from this slice */1.28 +};1.29 +1.30 +static struct TMU_timer TMU_timers[3];1.31 +1.32 uint32_t TMU_count( int timer, uint32_t nanosecs );1.33 +void TMU_schedule_timer( int timer );1.35 void TMU_event_callback( int eventid )1.36 {1.37 TMU_count( eventid - EVENT_TMU0, sh4r.slice_cycle );1.38 + assert( MMIO_READ( TMU, TCR0 + (eventid - EVENT_TMU0)*12 ) & 0x100 );1.39 }1.41 void TMU_init(void)1.42 @@ -128,19 +144,16 @@1.43 register_event_callback( EVENT_TMU2, TMU_event_callback );1.44 }1.46 -#define TCR_ICPF 0x02001.47 -#define TCR_UNF 0x01001.48 -#define TCR_UNIE 0x00201.49 +void TMU_dump(unsigned timer)1.50 +{1.51 + fprintf(stderr, "Timer %d: %s %08x/%08x %dns run: %08X - %08X\n",1.52 + timer, TMU_IS_RUNNING(timer) ? "running" : "stopped",1.53 + MMIO_READ(TMU, TCNT0 + (timer*12)), MMIO_READ(TMU, TCOR0 + (timer*12)),1.54 + TMU_timers[timer].timer_period,1.55 + TMU_timers[timer].timer_run,1.56 + TMU_timers[timer].timer_remainder );1.57 +}1.59 -#define TCR_IRQ_ACTIVE (TCR_UNF|TCR_UNIE)1.60 -1.61 -struct TMU_timer {1.62 - uint32_t timer_period;1.63 - uint32_t timer_remainder; /* left-over cycles from last count */1.64 - uint32_t timer_run; /* cycles already run from this slice */1.65 -};1.66 -1.67 -static struct TMU_timer TMU_timers[3];1.69 void TMU_set_timer_control( int timer, int tcr )1.70 {1.71 @@ -188,17 +201,31 @@1.72 period = sh4_peripheral_period; /* I dunno... */1.73 break;1.74 }1.75 - TMU_timers[timer].timer_period = period;1.76 +1.77 + if( period != TMU_timers[timer].timer_period ) {1.78 + if( TMU_IS_RUNNING(timer) ) {1.79 + /* If we're changing clock speed while counting, sync up and reschedule */1.80 + TMU_count(timer, sh4r.slice_cycle);1.81 + TMU_timers[timer].timer_period = period;1.82 + TMU_schedule_timer(timer);1.83 + } else {1.84 + TMU_timers[timer].timer_period = period;1.85 + }1.86 + }1.88 MMIO_WRITE( TMU, TCR0 + (12*timer), tcr );1.89 }1.91 void TMU_schedule_timer( int timer )1.92 {1.93 - uint64_t duration = (uint64_t)((uint32_t)(MMIO_READ( TMU, TCNT0 + 12*timer )+1)) *1.94 + uint64_t duration = ((uint64_t)((uint32_t)(MMIO_READ( TMU, TCNT0 + 12*timer )))+1) *1.95 (uint64_t)TMU_timers[timer].timer_period - TMU_timers[timer].timer_remainder;1.96 event_schedule_long( EVENT_TMU0+timer, (uint32_t)(duration / 1000000000),1.97 (uint32_t)(duration % 1000000000) );1.98 +// if( timer == 2 ) {1.99 +// WARN( "Schedule timer %d: %lldns", timer, duration );1.100 +// TMU_dump(timer);1.101 +// }1.102 }1.104 void TMU_start( int timer )1.105 @@ -230,6 +257,8 @@1.106 uint32_t count = run_ns / TMU_timers[timer].timer_period;1.107 uint32_t value = MMIO_READ( TMU, TCNT0 + 12*timer );1.108 uint32_t reset = MMIO_READ( TMU, TCOR0 + 12*timer );1.109 +// if( timer == 2 )1.110 +// WARN( "Counting timer %d: %d ns, %d ticks", timer, run_ns, count );1.111 if( count > value ) {1.112 uint32_t tcr = MMIO_READ( TMU, TCR0 + 12*timer );1.113 tcr |= TCR_UNF;1.114 @@ -239,6 +268,8 @@1.115 if( tcr & TCR_UNIE )1.116 intc_raise_interrupt( INT_TMU_TUNI0 + timer );1.117 MMIO_WRITE( TMU, TCNT0 + 12*timer, value );1.118 +// if( timer == 2 )1.119 +// WARN( "Underflowed timer %d", timer );1.120 TMU_schedule_timer(timer);1.121 } else {1.122 value -= count;
.