mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2
@ 2026-10-30 15:53 Simon Schuster
  2026-10-30 15:53 ` [PATCH 1/3] nios2: remove usage of libgcc Simon Schuster
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Simon Schuster @ 2026-10-30 15:53 UTC (permalink / raw)
  To: Dinh Nguyen, Andrew Morton, Arnd Bergmann
  Cc: Sasha Levin, linux-kernel, Simon Schuster

Recently, there have been linking failures on nios2 regarding libgcc
symbols that we reexport to modules (in particular __mulsi3 [0], and
__divsi3_table [1]).

In the resulting discussion, Arnd suggested [2] dropping the libgcc
dependency altogether, as -- while specific functions might be fine --
libgcc does not expect to run in a kernel-like freestanding environment.

To this end, Dinh Nguyen was kind enough to locate and extract
GPLv2-compliant versions of the software mul/div/mod and __gcc_bcmp
functions required by nios2 gcc and integrate them into the kernel.

As Arnd also suggested [3] that these might be helpful to other smaller
architectures (such as arc or openrisc), I've further extracted them to
lib/ with corresponding CONFIG_GENERIC_LIB_* options that allow
selectively enabling and exporting these as required.

The patch series compiles mostly^4 fine in a nios2 allyesconfig
without modpost errors; a quick boot test on a regular build also
completed successfully.

One aspect I'm not fully sure of is whether adding declarations for the
new lib/ functions to include/linux/libgcc.h unconditionally in the last
patch of this series is completely clean; but it matches how other
"optional vendored" functions in libgcc.h seem to be handled.

Best regards,
Simon

0: https://lore.kernel.org/lkml/20261019-nios2-mulsi3-v1-1-4fd75b1bacef@linutronix.de/
1: https://lore.kernel.org/lkml/20261026234452.1086974-1-sashal@kernel.org/
2: https://lore.kernel.org/lkml/686f4ca2-0fb6-4a73-9cdb-0edcccafdd62@app.fastmail.com/
3: https://lore.kernel.org/lkml/426c73b7-b4dc-4b68-9aa5-6145a13280bc@app.fastmail.com/
4: There seems to be an unrelated issue in linux-next regarding
   CONFIG_PNFS_BLOCK, furthermore -Wno-attribute-alias
   -Wno-missing-prototypes -Wno-missing-declarations and
   -Wno-unused-function were required due to unrelated Werror-related
   compilation issues; but as this series concerns compiler intrinsics
   that are never explictly referenced in code and it links fine this
   seems acceptable to me.

Signed-off-by: Simon Schuster <schuster.simon@siemens-energy.com>
---
Dinh Nguyen (1):
      nios2: remove usage of libgcc

Simon Schuster (2):
      nios2: export __divsi3_table
      lib: extract 32bit mul/div helpers from nios2 into GENERIC_LIB

 arch/nios2/Kconfig              | 11 +++++
 arch/nios2/Makefile             |  4 +-
 arch/nios2/kernel/nios2_ksyms.c | 22 ----------
 arch/nios2/lib/Makefile         |  1 +
 arch/nios2/lib/math.c           | 26 ++++++++++++
 include/linux/libgcc.h          | 12 ++++++
 lib/Kconfig                     | 18 ++++++++
 lib/Makefile                    | 11 +++++
 lib/divmod.c                    | 94 +++++++++++++++++++++++++++++++++++++++++
 lib/gccbcmp.c                   | 13 ++++++
 lib/mulsi3.c                    | 24 +++++++++++
 11 files changed, 211 insertions(+), 25 deletions(-)
---
base-commit: a39c950806213f6861d00f90729acaaa21f2d95a
change-id: 20261030-nios2-remove-usage-of-libgcc-63d9d0faad62

Best regards,
-- 
Simon Schuster <schuster.simon@siemens-energy.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] nios2: remove usage of libgcc
  2026-10-30 15:53 [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Simon Schuster
@ 2026-10-30 15:53 ` Simon Schuster
  2026-10-30 15:53 ` [PATCH 2/3] nios2: export __divsi3_table Simon Schuster
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Simon Schuster @ 2026-10-30 15:53 UTC (permalink / raw)
  To: Dinh Nguyen, Andrew Morton, Arnd Bergmann
  Cc: Sasha Levin, linux-kernel, Simon Schuster

From: Dinh Nguyen <dinguyen@kernel.org>

Use the kernel's runtime support for lshrdi3, ashldi3, ashrdi3, muldi3,
and ucmpdi2.

Copy over the math functions from a GPLv2 GCC implementation of divsi3,
udivsi3, mulsi3, umulsi3, modsi3, and gcc_bcmp.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Signed-off-by: Simon Schuster <schuster.simon@siemens-energy.com>
---
 arch/nios2/Kconfig              |   5 ++
 arch/nios2/Makefile             |   4 +-
 arch/nios2/kernel/nios2_ksyms.c |  22 --------
 arch/nios2/lib/Makefile         |   1 +
 arch/nios2/lib/math.c           | 119 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 126 insertions(+), 25 deletions(-)

diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 9c0e6eaeb005c..9417bcf583957 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -14,6 +14,11 @@ config NIOS2
 	select GENERIC_CPU_DEVICES
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
+	select GENERIC_LIB_LSHRDI3
+	select GENERIC_LIB_ASHLDI3
+	select GENERIC_LIB_ASHRDI3
+	select GENERIC_LIB_MULDI3
+	select GENERIC_LIB_UCMPDI2
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_KGDB
 	select HAVE_PAGE_SIZE_4KB
diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile
index f1ff4ce0f1a2c..173588c31abf9 100644
--- a/arch/nios2/Makefile
+++ b/arch/nios2/Makefile
@@ -19,8 +19,6 @@ UTS_SYSNAME = Linux
 
 export MMU
 
-LIBGCC         := $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
-
 KBUILD_AFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION)
 
 KBUILD_CFLAGS += -pipe -D__linux__ -D__ELF__
@@ -37,7 +35,7 @@ KBUILD_CFLAGS += -DUTS_SYSNAME=\"$(UTS_SYSNAME)\"
 KBUILD_CFLAGS += -fno-builtin
 KBUILD_CFLAGS += -G 0
 
-libs-y		+= arch/nios2/lib/ $(LIBGCC)
+libs-y		+= arch/nios2/lib/
 
 INSTALL_PATH ?= /tftpboot
 nios2-boot := arch/$(ARCH)/boot
diff --git a/arch/nios2/kernel/nios2_ksyms.c b/arch/nios2/kernel/nios2_ksyms.c
index e8710a269b398..351664e236fac 100644
--- a/arch/nios2/kernel/nios2_ksyms.c
+++ b/arch/nios2/kernel/nios2_ksyms.c
@@ -21,25 +21,3 @@ EXPORT_SYMBOL(memmove);
 /* memory management */
 
 EXPORT_SYMBOL(flush_icache_range);
-
-/*
- * libgcc functions - functions that are used internally by the
- * compiler...  (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-#define DECLARE_EXPORT(name)	extern void name(void); EXPORT_SYMBOL(name)
-
-DECLARE_EXPORT(__gcc_bcmp);
-DECLARE_EXPORT(__divsi3);
-DECLARE_EXPORT(__moddi3);
-DECLARE_EXPORT(__modsi3);
-DECLARE_EXPORT(__udivmoddi4);
-DECLARE_EXPORT(__udivsi3);
-DECLARE_EXPORT(__umoddi3);
-DECLARE_EXPORT(__umodsi3);
-DECLARE_EXPORT(__muldi3);
-DECLARE_EXPORT(__mulsi3);
-DECLARE_EXPORT(__ucmpdi2);
-DECLARE_EXPORT(__lshrdi3);
-DECLARE_EXPORT(__ashldi3);
-DECLARE_EXPORT(__ashrdi3);
diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile
index 9d5bf1df520c1..86433dcaac7e5 100644
--- a/arch/nios2/lib/Makefile
+++ b/arch/nios2/lib/Makefile
@@ -7,3 +7,4 @@ lib-y += delay.o
 lib-y += memcpy.o
 lib-y += memmove.o
 lib-y += memset.o
+lib-y += math.o
diff --git a/arch/nios2/lib/math.c b/arch/nios2/lib/math.c
new file mode 100644
index 0000000000000..9a89fa268a96e
--- /dev/null
+++ b/arch/nios2/lib/math.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright Altera Corporation (C) 2026. All rights reserved.
+ */
+
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+/*
+ * Software 32-bit multiply for cores built without the hardware multiplier.
+ */
+s32 __mulsi3(s32 a, s32 b);
+s32 __divsi3(s32 a, s32 b);
+s32 __udivsi3(s32 a, s32 b);
+s32 __modsi3(s32 a, s32 b);
+s32 __umodsi3(s32 a, s32 b);
+int __gcc_bcmp(const void *s1, const void *s2, size_t len);
+
+static u32 udivmodsi4(u32 num, u32 den, int modwanted)
+{
+	u32 bit = 1;
+	u32 res = 0;
+
+	while (den < num && bit && !(den & (1U << 31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+
+	return modwanted ? num : res;
+}
+
+s32 __mulsi3(s32 a, s32 b)
+{
+	s32 res = 0;
+	u32 cnt = a;
+
+	while (cnt) {
+		if (cnt & 1)
+			res += b;
+
+		b <<= 1;
+		cnt >>= 1;
+	}
+
+	return res;
+}
+EXPORT_SYMBOL(__mulsi3);
+
+s32 __divsi3(s32 a, s32 b)
+{
+	int neg = 0;
+	s32 res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4(a, b, 0);
+	if (neg)
+		res = -res;
+
+	return res;
+}
+EXPORT_SYMBOL(__divsi3);
+
+s32 __udivsi3(s32 a, s32 b)
+{
+	return udivmodsi4(a, b, 0);
+}
+EXPORT_SYMBOL(__udivsi3);
+
+s32 __modsi3(s32 a, s32 b)
+{
+	int neg = 0;
+	s32 res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4(a, b, 1);
+	if (neg)
+		res = -res;
+
+	return res;
+}
+EXPORT_SYMBOL(__modsi3);
+
+s32 __umodsi3(s32 a, s32 b)
+{
+	return udivmodsi4(a, b, 1);
+}
+EXPORT_SYMBOL(__umodsi3);
+
+int __gcc_bcmp(const void *s1, const void *s2, size_t len)
+{
+	return memcmp(s1, s2, len);
+}
+EXPORT_SYMBOL(__gcc_bcmp);
+

-- 
2.39.5


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] nios2: export __divsi3_table
  2026-10-30 15:53 [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Simon Schuster
  2026-10-30 15:53 ` [PATCH 1/3] nios2: remove usage of libgcc Simon Schuster
@ 2026-10-30 15:53 ` Simon Schuster
  2026-10-30 15:53 ` [PATCH 3/3] lib: extract 32bit mul/div helpers from nios2 into GENERIC_LIB Simon Schuster
  2026-10-30 16:50 ` [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Arnd Bergmann
  3 siblings, 0 replies; 5+ messages in thread
From: Simon Schuster @ 2026-10-30 15:53 UTC (permalink / raw)
  To: Dinh Nguyen, Andrew Morton, Arnd Bergmann
  Cc: Sasha Levin, linux-kernel, Simon Schuster

As noted in <20261026234452.1086974-1-sashal@kernel.org>, gcc can
occasionally emit references to __divsi3_table, so we need to include
that one in libgcc-less builds, as well.

The definition originates from gcc/config/nios2/lib2-divtable.c that
was distributed in source by Altera as part of the nios2eds in
gcc 3.4.1 (Altera Nios II 6.1 b197) under GPLv2 or later.

lib2-divtable.c does not carry an explicit copyright notice in the gcc
release, the associated nios2.h is: Copyright (C) 2005 Altera.

Nonetheless, the table can also be regenerated by the following snippet:

perl -e 'for my $row (0..15) {
  print join(", ", map { $_ == 0 ? 0 : "$row/$_" } 0..15), ",\n";
}'

Signed-off-by: Simon Schuster <schuster.simon@siemens-energy.com>
---
 arch/nios2/lib/math.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/nios2/lib/math.c b/arch/nios2/lib/math.c
index 9a89fa268a96e..f4a4e7d1afeee 100644
--- a/arch/nios2/lib/math.c
+++ b/arch/nios2/lib/math.c
@@ -117,3 +117,22 @@ int __gcc_bcmp(const void *s1, const void *s2, size_t len)
 }
 EXPORT_SYMBOL(__gcc_bcmp);
 
+u8 __divsi3_table[] = {
+0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
+0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
+0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
+0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
+0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
+0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
+0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
+0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
+0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
+0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
+0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
+0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
+0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
+0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
+0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
+0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
+};
+EXPORT_SYMBOL(__divsi3_table);

-- 
2.39.5


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] lib: extract 32bit mul/div helpers from nios2 into GENERIC_LIB
  2026-10-30 15:53 [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Simon Schuster
  2026-10-30 15:53 ` [PATCH 1/3] nios2: remove usage of libgcc Simon Schuster
  2026-10-30 15:53 ` [PATCH 2/3] nios2: export __divsi3_table Simon Schuster
@ 2026-10-30 15:53 ` Simon Schuster
  2026-10-30 16:50 ` [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Arnd Bergmann
  3 siblings, 0 replies; 5+ messages in thread
From: Simon Schuster @ 2026-10-30 15:53 UTC (permalink / raw)
  To: Dinh Nguyen, Andrew Morton, Arnd Bergmann
  Cc: Sasha Levin, linux-kernel, Simon Schuster

As suggested in 426c73b7-b4dc-4b68-9aa5-6145a13280bc@app.fastmail.com,
the software emulation of div/mul/mod on 32-bit platforms from nios2
might be of use to other smaller architectures as well when trying to
drop their libgcc dependency (e.g., arc, openrisc). The same applies to
__gcc_bcmp.
Therefore, extract and add them to lib/, guarded by respective
CONFIG_GENERIC_LIB_* options.

Symbols covered:
s32 __mulsi3(s32 a, s32 b);
s32 __divsi3(s32 a, s32 b);
s32 __udivsi3(s32 a, s32 b);
s32 __modsi3(s32 a, s32 b);
s32 __umodsi3(s32 a, s32 b);
int __gcc_bcmp(const void *s1, const void *s2, size_t len);

Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Simon Schuster <schuster.simon@siemens-energy.com>
---
 arch/nios2/Kconfig     |   6 +++
 arch/nios2/lib/math.c  | 112 -------------------------------------------------
 include/linux/libgcc.h |  12 ++++++
 lib/Kconfig            |  18 ++++++++
 lib/Makefile           |  11 +++++
 lib/divmod.c           |  94 +++++++++++++++++++++++++++++++++++++++++
 lib/gccbcmp.c          |  13 ++++++
 lib/mulsi3.c           |  24 +++++++++++
 8 files changed, 178 insertions(+), 112 deletions(-)

diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 9417bcf583957..08db6aa9c396f 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -19,6 +19,12 @@ config NIOS2
 	select GENERIC_LIB_ASHRDI3
 	select GENERIC_LIB_MULDI3
 	select GENERIC_LIB_UCMPDI2
+	select GENERIC_LIB_DIVSI3
+	select GENERIC_LIB_MODSI3
+	select GENERIC_LIB_UDIVSI3
+	select GENERIC_LIB_UMODSI3
+	select GENERIC_LIB_MULSI3
+	select GENERIC_LIB_GCC_BCMP
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_KGDB
 	select HAVE_PAGE_SIZE_4KB
diff --git a/arch/nios2/lib/math.c b/arch/nios2/lib/math.c
index f4a4e7d1afeee..ba16b57019227 100644
--- a/arch/nios2/lib/math.c
+++ b/arch/nios2/lib/math.c
@@ -3,120 +3,8 @@
  */
 
 #include <linux/export.h>
-#include <linux/string.h>
 #include <linux/types.h>
 
-/*
- * Software 32-bit multiply for cores built without the hardware multiplier.
- */
-s32 __mulsi3(s32 a, s32 b);
-s32 __divsi3(s32 a, s32 b);
-s32 __udivsi3(s32 a, s32 b);
-s32 __modsi3(s32 a, s32 b);
-s32 __umodsi3(s32 a, s32 b);
-int __gcc_bcmp(const void *s1, const void *s2, size_t len);
-
-static u32 udivmodsi4(u32 num, u32 den, int modwanted)
-{
-	u32 bit = 1;
-	u32 res = 0;
-
-	while (den < num && bit && !(den & (1U << 31))) {
-		den <<= 1;
-		bit <<= 1;
-	}
-
-	while (bit) {
-		if (num >= den) {
-			num -= den;
-			res |= bit;
-		}
-		bit >>= 1;
-		den >>= 1;
-	}
-
-	return modwanted ? num : res;
-}
-
-s32 __mulsi3(s32 a, s32 b)
-{
-	s32 res = 0;
-	u32 cnt = a;
-
-	while (cnt) {
-		if (cnt & 1)
-			res += b;
-
-		b <<= 1;
-		cnt >>= 1;
-	}
-
-	return res;
-}
-EXPORT_SYMBOL(__mulsi3);
-
-s32 __divsi3(s32 a, s32 b)
-{
-	int neg = 0;
-	s32 res;
-
-	if (a < 0) {
-		a = -a;
-		neg = !neg;
-	}
-
-	if (b < 0) {
-		b = -b;
-		neg = !neg;
-	}
-
-	res = udivmodsi4(a, b, 0);
-	if (neg)
-		res = -res;
-
-	return res;
-}
-EXPORT_SYMBOL(__divsi3);
-
-s32 __udivsi3(s32 a, s32 b)
-{
-	return udivmodsi4(a, b, 0);
-}
-EXPORT_SYMBOL(__udivsi3);
-
-s32 __modsi3(s32 a, s32 b)
-{
-	int neg = 0;
-	s32 res;
-
-	if (a < 0) {
-		a = -a;
-		neg = 1;
-	}
-
-	if (b < 0)
-		b = -b;
-
-	res = udivmodsi4(a, b, 1);
-	if (neg)
-		res = -res;
-
-	return res;
-}
-EXPORT_SYMBOL(__modsi3);
-
-s32 __umodsi3(s32 a, s32 b)
-{
-	return udivmodsi4(a, b, 1);
-}
-EXPORT_SYMBOL(__umodsi3);
-
-int __gcc_bcmp(const void *s1, const void *s2, size_t len)
-{
-	return memcmp(s1, s2, len);
-}
-EXPORT_SYMBOL(__gcc_bcmp);
-
 u8 __divsi3_table[] = {
 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
diff --git a/include/linux/libgcc.h b/include/linux/libgcc.h
index 0d68f9d6a6a7e..85d7b7b0f1949 100644
--- a/include/linux/libgcc.h
+++ b/include/linux/libgcc.h
@@ -7,6 +7,7 @@
 #define __LIB_LIBGCC_H
 
 #include <asm/byteorder.h>
+#include <linux/types.h>
 
 typedef int word_type __attribute__ ((mode (__word__)));
 
@@ -34,6 +35,17 @@ long long notrace __lshrdi3(long long u, word_type b);
 long long notrace __muldi3(long long u, long long v);
 word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b);
 
+/*
+ * Software 32-bit multiply for cores built without the hardware multiplier.
+ */
+s32 notrace __mulsi3(s32 a, s32 b);
+s32 notrace __divsi3(s32 a, s32 b);
+s32 notrace __udivsi3(s32 a, s32 b);
+s32 notrace __modsi3(s32 a, s32 b);
+s32 notrace __umodsi3(s32 a, s32 b);
+
+int __gcc_bcmp(const void *s1, const void *s2, size_t len);
+
 #ifdef CONFIG_HAVE_ARCH_LIBGCC_H
 #include <asm/libgcc.h>
 #endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 1e42f5167c68b..91a36aad2e625 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -611,6 +611,24 @@ config GENERIC_LIB_CMPDI2
 config GENERIC_LIB_UCMPDI2
 	bool
 
+config GENERIC_LIB_DIVSI3
+	bool
+
+config GENERIC_LIB_MODSI3
+	bool
+
+config GENERIC_LIB_UDIVSI3
+	bool
+
+config GENERIC_LIB_UMODSI3
+	bool
+
+config GENERIC_LIB_MULSI3
+	bool
+
+config GENERIC_LIB_GCC_BCMP
+	bool
+
 config GENERIC_LIB_DEVMEM_IS_ALLOWED
 	bool
 
diff --git a/lib/Makefile b/lib/Makefile
index a2afe954805cb..671ff5de1c397 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -337,6 +337,17 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
 obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
 obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
 obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
+obj-$(CONFIG_GENERIC_LIB_MULSI3) += mulsi3.o
+obj-$(CONFIG_GENERIC_LIB_GCC_BCMP) += gccbcmp.o
+
+divmod-needed := $(or \
+	$(CONFIG_GENERIC_LIB_DIVSI3),\
+	$(CONFIG_GENERIC_LIB_MODSI3),\
+	$(CONFIG_GENERIC_LIB_UDIVSI3),\
+	$(CONFIG_GENERIC_LIB_UMODSI3))
+obj-$(divmod-needed) += divmod.o
+
+
 obj-$(CONFIG_OBJAGG) += objagg.o
 
 # pldmfw library
diff --git a/lib/divmod.c b/lib/divmod.c
new file mode 100644
index 0000000000000..cc1df6f9978ce
--- /dev/null
+++ b/lib/divmod.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright Altera Corporation (C) 2026. All rights reserved.
+ */
+
+#include <linux/libgcc.h>
+#include <linux/export.h>
+#include <linux/types.h>
+
+static u32 udivmodsi4(u32 num, u32 den, int modwanted)
+{
+	u32 bit = 1;
+	u32 res = 0;
+
+	while (den < num && bit && !(den & (1U << 31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+
+	return modwanted ? num : res;
+}
+
+
+#ifdef CONFIG_GENERIC_LIB_DIVSI3
+s32 __divsi3(s32 a, s32 b)
+{
+	int neg = 0;
+	s32 res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4(a, b, 0);
+	if (neg)
+		res = -res;
+
+	return res;
+}
+EXPORT_SYMBOL(__divsi3);
+#endif
+
+#ifdef CONFIG_GENERIC_LIB_MODSI3
+s32 __modsi3(s32 a, s32 b)
+{
+	int neg = 0;
+	s32 res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4(a, b, 1);
+	if (neg)
+		res = -res;
+
+	return res;
+}
+EXPORT_SYMBOL(__modsi3);
+#endif
+
+#ifdef CONFIG_GENERIC_LIB_UDIVSI3
+s32 __udivsi3(s32 a, s32 b)
+{
+	return udivmodsi4(a, b, 0);
+}
+EXPORT_SYMBOL(__udivsi3);
+#endif
+
+#ifdef CONFIG_GENERIC_LIB_UMODSI3
+s32 __umodsi3(s32 a, s32 b)
+{
+	return udivmodsi4(a, b, 1);
+}
+EXPORT_SYMBOL(__umodsi3);
+#endif
diff --git a/lib/gccbcmp.c b/lib/gccbcmp.c
new file mode 100644
index 0000000000000..7037176b04b35
--- /dev/null
+++ b/lib/gccbcmp.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright Altera Corporation (C) 2026. All rights reserved.
+ */
+
+#include <linux/libgcc.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+int __gcc_bcmp(const void *s1, const void *s2, size_t len)
+{
+	return memcmp(s1, s2, len);
+}
+EXPORT_SYMBOL(__gcc_bcmp);
diff --git a/lib/mulsi3.c b/lib/mulsi3.c
new file mode 100644
index 0000000000000..6596a6598de05
--- /dev/null
+++ b/lib/mulsi3.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright Altera Corporation (C) 2026. All rights reserved.
+ */
+
+#include <linux/libgcc.h>
+#include <linux/export.h>
+#include <linux/types.h>
+
+s32 __mulsi3(s32 a, s32 b)
+{
+	s32 res = 0;
+	u32 cnt = a;
+
+	while (cnt) {
+		if (cnt & 1)
+			res += b;
+
+		b <<= 1;
+		cnt >>= 1;
+	}
+
+	return res;
+}
+EXPORT_SYMBOL(__mulsi3);

-- 
2.39.5


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2
  2026-10-30 15:53 [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Simon Schuster
                   ` (2 preceding siblings ...)
  2026-10-30 15:53 ` [PATCH 3/3] lib: extract 32bit mul/div helpers from nios2 into GENERIC_LIB Simon Schuster
@ 2026-10-30 16:50 ` Arnd Bergmann
  3 siblings, 0 replies; 5+ messages in thread
From: Arnd Bergmann @ 2026-10-30 16:50 UTC (permalink / raw)
  To: schuster.simon, Dinh Nguyen, Andrew Morton; +Cc: Sasha Levin, linux-kernel

On Fri, Oct 30, 2026, at 16:53, Simon Schuster wrote:
> Recently, there have been linking failures on nios2 regarding libgcc
> symbols that we reexport to modules (in particular __mulsi3 [0], and
> __divsi3_table [1]).
>
> In the resulting discussion, Arnd suggested [2] dropping the libgcc
> dependency altogether, as -- while specific functions might be fine --
> libgcc does not expect to run in a kernel-like freestanding environment.
>
> To this end, Dinh Nguyen was kind enough to locate and extract
> GPLv2-compliant versions of the software mul/div/mod and __gcc_bcmp
> functions required by nios2 gcc and integrate them into the kernel.
>
> As Arnd also suggested [3] that these might be helpful to other smaller
> architectures (such as arc or openrisc), I've further extracted them to
> lib/ with corresponding CONFIG_GENERIC_LIB_* options that allow
> selectively enabling and exporting these as required.
>
> The patch series compiles mostly^4 fine in a nios2 allyesconfig
> without modpost errors; a quick boot test on a regular build also
> completed successfully.

This looks very good to me overall, thanks for working on this.

Just a few minor things that stood out:

- I don't see a need to add the files under arch/ first and then
  move them to lib/, just start with the added files there

- I did not expect gccbcmp.c to be needed at all, the kernel
  should handle the string functions internally. If you do need it,
  there is of course no harm adding it, but probably need to
  build with -ffreestanding to prevent it from recursively
  ending up in bcmp()

> One aspect I'm not fully sure of is whether adding declarations for the
> new lib/ functions to include/linux/libgcc.h unconditionally in the last
> patch of this series is completely clean; but it matches how other
> "optional vendored" functions in libgcc.h seem to be handled.

That part is looks fine.

      Arnd

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-30 16:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 15:53 [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Simon Schuster
2026-10-30 15:53 ` [PATCH 1/3] nios2: remove usage of libgcc Simon Schuster
2026-10-30 15:53 ` [PATCH 2/3] nios2: export __divsi3_table Simon Schuster
2026-10-30 15:53 ` [PATCH 3/3] lib: extract 32bit mul/div helpers from nios2 into GENERIC_LIB Simon Schuster
2026-10-30 16:50 ` [PATCH 0/3] lib: Add software mul/div helpers and use them from nios2 Arnd Bergmann

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

all inboxes | Powered by JetHome®