Alpha arch development list
 help / color / mirror / Atom feed
* [PATCH v3] alpha: select ARCH_SUPPORTS_INT128
@ 2026-10-17 17:40 Matt Turner
  0 siblings, 0 replies; only message in thread
From: Matt Turner @ 2026-10-17 17:40 UTC (permalink / raw)
  To: linux-alpha; +Cc: Magnus Lindholm, Richard Henderson, linux-kernel

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>
---
v3:
- Fold in "alpha: add 128-bit shift helpers" so the select never lands
  without the libgcc shift routines that -Os builds need
  (https://lore.kernel.org/r/20261010022039.1610210-1-mattst88@gmail.com,
  reported at https://lore.kernel.org/oe-kbuild-all/202610090831.DSxrGQRc-lkp@intel.com/)
- Mark the helpers noinstr, as s390 does
- Drop Magnus's Reviewed-by and Tested-by given the new code

 arch/alpha/Kconfig                      |  1 +
 arch/alpha/include/asm/asm-prototypes.h |  6 +++
 arch/alpha/lib/Makefile                 |  2 +
 arch/alpha/lib/tishift.c                | 70 +++++++++++++++++++++++++
 4 files changed, 79 insertions(+)
 create mode 100644 arch/alpha/lib/tishift.c

diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 2672971b83f3..bed3f1c8d9d2 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -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
diff --git a/arch/alpha/include/asm/asm-prototypes.h b/arch/alpha/include/asm/asm-prototypes.h
index c8ae46fc2e74..672fea15032f 100644
--- a/arch/alpha/include/asm/asm-prototypes.h
+++ b/arch/alpha/include/asm/asm-prototypes.h
@@ -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
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 84046e730e6d..f77d4a46f2e6 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -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
diff --git a/arch/alpha/lib/tishift.c b/arch/alpha/lib/tishift.c
new file mode 100644
index 000000000000..8319907d8150
--- /dev/null
+++ b/arch/alpha/lib/tishift.c
@@ -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);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-17 17:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 17:40 [PATCH v3] alpha: select ARCH_SUPPORTS_INT128 Matt Turner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox