ARM timer counts down, not up.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2214 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2006-11-14 21:13:53 +00:00
parent 417f38f066
commit ec2db7de7a
1 changed files with 5 additions and 5 deletions

View File

@ -107,29 +107,29 @@ static void arm_timer_update(arm_timer_state *s, int64_t now)
/* Return the current value of the timer. */ /* Return the current value of the timer. */
static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now) static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
{ {
int64_t elapsed; int64_t left;
int64_t period; int64_t period;
if (s->count == 0) if (s->count == 0)
return 0; return 0;
if ((s->control & TIMER_CTRL_ENABLE) == 0) if ((s->control & TIMER_CTRL_ENABLE) == 0)
return s->count; return s->count;
elapsed = now - s->loaded; left = s->expires - now;
period = s->expires - s->loaded; period = s->expires - s->loaded;
/* If the timer should have expired then return 0. This can happen /* If the timer should have expired then return 0. This can happen
when the host timer signal doesnt occur immediately. It's better to when the host timer signal doesnt occur immediately. It's better to
have a timer appear to sit at zero for a while than have it wrap have a timer appear to sit at zero for a while than have it wrap
around before the guest interrupt is raised. */ around before the guest interrupt is raised. */
/* ??? Could we trigger the interrupt here? */ /* ??? Could we trigger the interrupt here? */
if (elapsed > period) if (left < 0)
return 0; return 0;
/* We need to calculate count * elapsed / period without overfowing. /* We need to calculate count * elapsed / period without overfowing.
Scale both elapsed and period so they fit in a 32-bit int. */ Scale both elapsed and period so they fit in a 32-bit int. */
while (period != (int32_t)period) { while (period != (int32_t)period) {
period >>= 1; period >>= 1;
elapsed >>= 1; left >>= 1;
} }
return ((uint64_t)s->count * (uint64_t)(int32_t)elapsed) return ((uint64_t)s->count * (uint64_t)(int32_t)left)
/ (int32_t)period; / (int32_t)period;
} }