BUG/MINOR: tools: fix the i386 version of the div64_32 function

As reported in issue #596, the edx register isn't marked as clobbered
in div64_32(), which could technically allow gcc to try to reuse it
if it needed a copy of the 32 highest bits of the o1 register after
the operation.

Two attempts were tried, one using a dummy 32-bit local variable to
store the intermediary edx and another one switching to "=A" and making
result a long long. It turns out the former makes the resulting object
code significantly dirtier while the latter makes it better and was
kept. This is due to gcc's difficulties at working with register pairs
mixing 32- and 64- bit values on i386. It was verified that no code
change happened at all on x86_64, armv7, aarch64 nor mips32.

In practice it's only used by the frequency counters so this bug
cannot even be triggered but better fix it.

This may be backported to stable branches though it will not fix any
issue.
This commit is contained in:
Willy Tarreau 2020-04-23 17:08:02 +02:00
parent d7f8bd9b40
commit 09568fd54d

View File

@ -838,10 +838,10 @@ static inline unsigned int mul32hi(unsigned int a, unsigned int b)
*/
static inline unsigned int div64_32(unsigned long long o1, unsigned int o2)
{
unsigned int result;
unsigned long long result;
#ifdef __i386__
asm("divl %2"
: "=a" (result)
: "=A" (result)
: "A"(o1), "rm"(o2));
#else
result = o1 / o2;