mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
alpha: select ARCH_SUPPORTS_INT128
gcc supports __int128 on Alpha, and the 64x64 to 128-bit multiply that the users in the scheduler and in lib/ care about maps onto mulq/umulh rather than an out-of-line libgcc helper. Variable 128-bit shifts are another matter. gcc open-codes them when optimizing for speed, but with CONFIG_CC_OPTIMIZE_FOR_SIZE=y it calls the libgcc routines __ashlti3, __ashrti3 and __lshrti3 instead. The kernel does not link against libgcc, so provide the three helpers in C, as s390 does, and export them for modules. They are built into the kernel proper rather than lib.a so the exports are present even when nothing built in references them. Like the s390 versions they are marked noinstr, since the compiler may emit calls to them from noinstr code. Gate the select on CC_HAS_INT128 as the other 64-bit architectures do. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Matt Turner <mattst88@gmail.com> Tested-by: Magnus Lindholm <linmag7@gmail.com> Reviewed-by: Magnus Lindholm <linmag7@gmail.com> Link: https://lore.kernel.org/r/20261017174007.695344-1-mattst88@gmail.com Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
This commit is contained in:
parent
d8df465bc4
commit
3382beeda2
|
|
@ -16,6 +16,7 @@ config ALPHA
|
|||
select ARCH_NO_PREEMPT
|
||||
select ARCH_NO_SG_CHAIN
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select FORCE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
|
|
|
|||
|
|
@ -17,3 +17,9 @@ extern void __remlu(void);
|
|||
extern void __divqu(void);
|
||||
extern void __remqu(void);
|
||||
extern unsigned long __udiv_qrnnd(unsigned long *, unsigned long, unsigned long , unsigned long);
|
||||
|
||||
#ifdef CONFIG_ARCH_SUPPORTS_INT128
|
||||
extern __int128_t __ashlti3(__int128_t a, int shift);
|
||||
extern __int128_t __ashrti3(__int128_t a, int shift);
|
||||
extern __int128_t __lshrti3(__int128_t a, int shift);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
|
|||
callback_srm.o srm_puts.o srm_printk.o \
|
||||
fls.o
|
||||
|
||||
obj-$(CONFIG_ARCH_SUPPORTS_INT128) += tishift.o
|
||||
|
||||
# The division routines are built from single source, with different defines.
|
||||
AFLAGS___divqu.o = -DDIV
|
||||
AFLAGS___remqu.o = -DREM
|
||||
|
|
|
|||
70
arch/alpha/lib/tishift.c
Normal file
70
arch/alpha/lib/tishift.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* 128-bit shift helpers.
|
||||
*
|
||||
* gcc open-codes a variable 128-bit shift when optimizing for speed, but
|
||||
* calls these libgcc routines when optimizing for size.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
|
||||
union ti {
|
||||
__int128_t val;
|
||||
struct {
|
||||
u64 low;
|
||||
u64 high;
|
||||
};
|
||||
};
|
||||
|
||||
noinstr __int128_t __ashlti3(__int128_t a, int shift)
|
||||
{
|
||||
union ti ti = { .val = a };
|
||||
|
||||
if (!shift)
|
||||
return ti.val;
|
||||
if (shift < 64) {
|
||||
ti.high = (ti.high << shift) | (ti.low >> (64 - shift));
|
||||
ti.low <<= shift;
|
||||
} else {
|
||||
ti.high = ti.low << (shift - 64);
|
||||
ti.low = 0;
|
||||
}
|
||||
return ti.val;
|
||||
}
|
||||
EXPORT_SYMBOL(__ashlti3);
|
||||
|
||||
noinstr __int128_t __ashrti3(__int128_t a, int shift)
|
||||
{
|
||||
union ti ti = { .val = a };
|
||||
|
||||
if (!shift)
|
||||
return ti.val;
|
||||
if (shift < 64) {
|
||||
ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
|
||||
ti.high = (s64)ti.high >> shift;
|
||||
} else {
|
||||
ti.low = (s64)ti.high >> (shift - 64);
|
||||
ti.high = (s64)ti.high >> 63;
|
||||
}
|
||||
return ti.val;
|
||||
}
|
||||
EXPORT_SYMBOL(__ashrti3);
|
||||
|
||||
noinstr __int128_t __lshrti3(__int128_t a, int shift)
|
||||
{
|
||||
union ti ti = { .val = a };
|
||||
|
||||
if (!shift)
|
||||
return ti.val;
|
||||
if (shift < 64) {
|
||||
ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
|
||||
ti.high >>= shift;
|
||||
} else {
|
||||
ti.low = ti.high >> (shift - 64);
|
||||
ti.high = 0;
|
||||
}
|
||||
return ti.val;
|
||||
}
|
||||
EXPORT_SYMBOL(__lshrti3);
|
||||
Loading…
Reference in New Issue
Block a user