Having an #ifdef CONFIG_X86 section in a common library is rude. Furthermore, for x86 the main logic is 6 bytes, meaning it's ripe for inlining. Create an x86-specific asm/muldiv.h implementing arch_muldiv64().
Signed-off-by: Andrew Cooper <[email protected]> --- CC: Jan Beulich <[email protected]> CC: Roger Pau Monné <[email protected]> CC: Stefano Stabellini <[email protected]> CC: Julien Grall <[email protected]> CC: Volodymyr Babchuk <[email protected]> CC: Bertrand Marquis <[email protected]> CC: Michal Orzel <[email protected]> CC: Oleksii Kurochko <[email protected]> bloat-o-meter results: add/remove: 0/1 grow/shrink: 1/2 up/down: 10/-39 (-29) Function old new delta get_count 240 250 +10 calibrate_apic_timer 211 203 -8 calibrate_tsc 190 177 -13 muldiv64 18 - -18 The increase in get_count is from different register scheduling. --- xen/arch/x86/include/asm/muldiv.h | 20 ++++++++++++++++++++ xen/include/xen/muldiv.h | 8 ++++++++ xen/lib/muldiv64.c | 8 -------- 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 xen/arch/x86/include/asm/muldiv.h diff --git a/xen/arch/x86/include/asm/muldiv.h b/xen/arch/x86/include/asm/muldiv.h new file mode 100644 index 000000000000..563cab0564da --- /dev/null +++ b/xen/arch/x86/include/asm/muldiv.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef X86_MULDIV_H +#define X86_MULDIV_H + +#include <xen/stdint.h> + +static inline uint64_t attr_const arch_muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ + asm_inline ( + "mulq %[b]\n\t" + "divq %[c]" + : "+a" (a) + : [b] "rm" ((uint64_t)b), [c] "rm" ((uint64_t)c) + : "rdx" ); + + return a; +} +#define arch_muldiv64 arch_muldiv64 + +#endif /* X86_MULDIV_H */ diff --git a/xen/include/xen/muldiv.h b/xen/include/xen/muldiv.h index 8ed2c68caf84..e7f8fdcf01ea 100644 --- a/xen/include/xen/muldiv.h +++ b/xen/include/xen/muldiv.h @@ -4,6 +4,10 @@ #include <xen/stdint.h> +#if __has_include(<asm/muldiv.h>) +# include <asm/muldiv.h> +#endif + uint64_t attr_const generic_muldiv64(uint64_t a, uint32_t b, uint32_t c); /* @@ -12,7 +16,11 @@ uint64_t attr_const generic_muldiv64(uint64_t a, uint32_t b, uint32_t c); */ static inline uint64_t attr_const muldiv64(uint64_t a, uint32_t b, uint32_t c) { +#ifdef arch_muldiv64 + return arch_muldiv64(a, b, c); +#else return generic_muldiv64(a, b, c); +#endif } #endif /* XEN_MULDIV_H */ diff --git a/xen/lib/muldiv64.c b/xen/lib/muldiv64.c index 5e6db1b2f4d2..6ee86d124a21 100644 --- a/xen/lib/muldiv64.c +++ b/xen/lib/muldiv64.c @@ -2,13 +2,6 @@ uint64_t generic_muldiv64(uint64_t a, uint32_t b, uint32_t c) { -#ifdef CONFIG_X86 - asm ( "mulq %1; divq %2" : "+a" (a) - : "rm" ((uint64_t)b), "rm" ((uint64_t)c) - : "rdx" ); - - return a; -#else union { uint64_t ll; struct { @@ -31,7 +24,6 @@ uint64_t generic_muldiv64(uint64_t a, uint32_t b, uint32_t c) res.l.low = (((rh % c) << 32) + (uint32_t)rl) / c; return res.ll; -#endif } /* -- 2.39.5
