Skip to content

Commit

Permalink
host-utils: Add muldiv64_round_up
Browse files Browse the repository at this point in the history
This will be used for converting time intervals in different base units
to host units, for the purpose of scheduling timers to emulate target
timers. Timers typically must not fire before their requested expiry
time but may fire some time afterward, so rounding up is the right way
to implement these.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
npiggin authored and legoater committed Sep 4, 2023
1 parent cbc259c commit 89eefd3
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion include/qemu/host-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
return (__int128_t)a * b / c;
}

static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
{
return ((__int128_t)a * b + c - 1) / c;
}

static inline uint64_t divu128(uint64_t *plow, uint64_t *phigh,
uint64_t divisor)
{
Expand Down Expand Up @@ -83,7 +88,8 @@ void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b);
uint64_t divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
int64_t divs128(uint64_t *plow, int64_t *phigh, int64_t divisor);

static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
static inline uint64_t __muldiv64(uint64_t a, uint32_t b, uint32_t c,
bool round_up)
{
union {
uint64_t ll;
Expand All @@ -99,12 +105,25 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)

u.ll = a;
rl = (uint64_t)u.l.low * (uint64_t)b;
if (round_up) {
rl += c - 1;
}
rh = (uint64_t)u.l.high * (uint64_t)b;
rh += (rl >> 32);
res.l.high = rh / c;
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
return res.ll;
}

static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
return __muldiv64(a, b, c, false);
}

static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
{
return __muldiv64(a, b, c, true);
}
#endif

/**
Expand Down

0 comments on commit 89eefd3

Please sign in to comment.