Loading hw/ptimer.c +31 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ */ #include "hw.h" #include "qemu-timer.h" #include "host-utils.h" struct ptimer_state { Loading Loading @@ -78,9 +78,39 @@ uint64_t ptimer_get_count(ptimer_state *s) } else { uint64_t rem; uint64_t div; uint32_t frac; int clz1, clz2; int shift; /* We need to divide time by period, where time is stored in rem (64-bit integer) and period is stored in period/period_frac (64.32 fixed point). Doing full precision division is hard, so scale values and do a 64-bit division. The result should be rounded down, so that the rounding error never causes the timer to go backwards. */ rem = s->next_event - now; div = s->period; clz1 = clz64(rem); clz2 = clz64(div); shift = clz1 < clz2 ? clz1 : clz2; rem <<= shift; div <<= shift; if (shift >= 32) { div |= ((uint64_t)s->period_frac << (shift - 32)); } else { if (shift != 0) div |= (s->period_frac >> (32 - shift)); /* Look at remaining bits of period_frac and round div up if necessary. */ if ((uint32_t)(s->period_frac << shift)) div += 1; } counter = rem / div; } } else { Loading Loading
hw/ptimer.c +31 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ */ #include "hw.h" #include "qemu-timer.h" #include "host-utils.h" struct ptimer_state { Loading Loading @@ -78,9 +78,39 @@ uint64_t ptimer_get_count(ptimer_state *s) } else { uint64_t rem; uint64_t div; uint32_t frac; int clz1, clz2; int shift; /* We need to divide time by period, where time is stored in rem (64-bit integer) and period is stored in period/period_frac (64.32 fixed point). Doing full precision division is hard, so scale values and do a 64-bit division. The result should be rounded down, so that the rounding error never causes the timer to go backwards. */ rem = s->next_event - now; div = s->period; clz1 = clz64(rem); clz2 = clz64(div); shift = clz1 < clz2 ? clz1 : clz2; rem <<= shift; div <<= shift; if (shift >= 32) { div |= ((uint64_t)s->period_frac << (shift - 32)); } else { if (shift != 0) div |= (s->period_frac >> (32 - shift)); /* Look at remaining bits of period_frac and round div up if necessary. */ if ((uint32_t)(s->period_frac << shift)) div += 1; } counter = rem / div; } } else { Loading