]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
m68k: Use kernel's generic muldi3 libgcc function
authorGreg Ungerer <gerg@linux-m68k.org>
Mon, 13 Nov 2023 13:32:09 +0000 (23:32 +1000)
committerGeert Uytterhoeven <geert@linux-m68k.org>
Mon, 9 Dec 2024 12:29:17 +0000 (13:29 +0100)
Use the kernels own generic lib/muldi3.c implementation of muldi3 for
68K machines. Some 68K CPUs support 64bit multiplies so move the arch
specific umul_ppmm() macro into a header file that is included by
lib/muldi3.c. That way it can take advantage of the single instruction
when available.

There does not appear to be any existing mechanism for the generic
lib/muldi3.c code to pick up an external arch definition of umul_ppmm().
Create an arch specific libgcc.h that can optionally be included by
the system include/linux/libgcc.h to allow for this.

Somewhat oddly there is also a similar definition of umul_ppmm() in
the non-architecture code in lib/crypto/mpi/longlong.h for a wide range
or machines. Its presence ends up complicating the include setup and
means not being able to use something like compiler.h instead. Actually
there is a few other defines of umul_ppmm() macros spread around in
various architectures, but not directly usable for the m68k case.

Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
Link: https://lore.kernel.org/20231113133209.1367286-1-gerg@linux-m68k.org
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
arch/Kconfig
arch/m68k/Kconfig
arch/m68k/include/asm/libgcc.h [new file with mode: 0644]
arch/m68k/lib/Makefile
arch/m68k/lib/muldi3.c [deleted file]
include/linux/libgcc.h

index 6682b2a53e342cbacc05b70ef99cb1c47efe55e8..b8a4ff36558228240080a5677f702d37f4f8d547 100644 (file)
@@ -1526,6 +1526,14 @@ config HAVE_ARCH_COMPILER_H
          linux/compiler-*.h in order to override macro definitions that those
          headers generally provide.
 
+config HAVE_ARCH_LIBGCC_H
+       bool
+       help
+         An architecture can select this if it provides an
+         asm/libgcc.h header that should be included after
+         linux/libgcc.h in order to override macro definitions that
+         header generally provides.
+
 config HAVE_ARCH_PREL32_RELOCATIONS
        bool
        help
index 7c4f7bcc89d76326b9d7280a3bcba79412ead7d2..b2ed0308c0eac207ff079e2a53ac637417f2ff5f 100644 (file)
@@ -23,7 +23,9 @@ config M68K
        select GENERIC_LIB_ASHLDI3
        select GENERIC_LIB_ASHRDI3
        select GENERIC_LIB_LSHRDI3
+       select GENERIC_LIB_MULDI3
        select HAS_IOPORT if PCI || ISA || ATARI_ROM_ISA
+       select HAVE_ARCH_LIBGCC_H
        select HAVE_ARCH_SECCOMP
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ASM_MODVERSIONS
diff --git a/arch/m68k/include/asm/libgcc.h b/arch/m68k/include/asm/libgcc.h
new file mode 100644 (file)
index 0000000..1cce6d1
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_M68K_LIBGCC_H
+#define __ASM_M68K_LIBGCC_H
+
+#ifndef CONFIG_CPU_HAS_NO_MULDIV64
+/*
+ * For those 68K CPUs that support 64bit multiply define umul_ppm()
+ * for the common muldi3 libgcc helper function (in lib/muldi3.c).
+ * CPUs that don't have it (like the original 68000 and ColdFire)
+ * will fallback to using the C-coded version of umul_ppmm().
+ */
+#define umul_ppmm(w1, w0, u, v)                                \
+       __asm__ ("mulu%.l %3,%1:%0"                     \
+                : "=d" ((unsigned long)(w0)),          \
+                  "=d" ((unsigned long)(w1))           \
+                : "%0" ((unsigned long)(u)),           \
+                  "dmi" ((unsigned long)(v)))
+#endif /* !CONFIG_CPU_HAS_NO_MULDIV64 */
+
+#endif /* __ASM_M68K_LIBGCC_H */
index 9158688e6cc625d188ee7bd3f3c0b76016e95def..15278a95259e87ed6ac919c04777c0e870482e54 100644 (file)
@@ -4,7 +4,7 @@
 # Makefile for m68k-specific library files..
 #
 
-lib-y  := muldi3.o memcpy.o memset.o memmove.o
+lib-y  := memcpy.o memset.o memmove.o
 
 lib-$(CONFIG_MMU) += uaccess.o
 lib-$(CONFIG_CPU_HAS_NO_MULDIV64) += mulsi3.o divsi3.o udivsi3.o
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
deleted file mode 100644 (file)
index 5012a9b..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 
-                          gcc-2.7.2.3/longlong.h which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details. */
-
-#include <linux/compiler.h>
-#include <linux/export.h>
-#include <linux/libgcc.h>
-
-#ifdef CONFIG_CPU_HAS_NO_MULDIV64
-
-#define SI_TYPE_SIZE 32
-#define __BITS4 (SI_TYPE_SIZE / 4)
-#define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
-
-#define umul_ppmm(w1, w0, u, v)                                                \
-  do {                                                                 \
-    USItype __x0, __x1, __x2, __x3;                                    \
-    USItype __ul, __vl, __uh, __vh;                                    \
-                                                                       \
-    __ul = __ll_lowpart (u);                                           \
-    __uh = __ll_highpart (u);                                          \
-    __vl = __ll_lowpart (v);                                           \
-    __vh = __ll_highpart (v);                                          \
-                                                                       \
-    __x0 = (USItype) __ul * __vl;                                      \
-    __x1 = (USItype) __ul * __vh;                                      \
-    __x2 = (USItype) __uh * __vl;                                      \
-    __x3 = (USItype) __uh * __vh;                                      \
-                                                                       \
-    __x1 += __ll_highpart (__x0);/* this can't give carry */           \
-    __x1 += __x2;              /* but this indeed can */               \
-    if (__x1 < __x2)           /* did we get it? */                    \
-      __x3 += __ll_B;          /* yes, add it in the proper pos. */    \
-                                                                       \
-    (w1) = __x3 + __ll_highpart (__x1);                                        \
-    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);         \
-  } while (0)
-
-#else
-
-#define umul_ppmm(w1, w0, u, v) \
-  __asm__ ("mulu%.l %3,%1:%0"                                          \
-           : "=d" ((USItype)(w0)),                                     \
-             "=d" ((USItype)(w1))                                      \
-           : "%0" ((USItype)(u)),                                      \
-             "dmi" ((USItype)(v)))
-
-#endif
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;                                                       \
-    umul_ppmm (__w.s.high, __w.s.low, u, v);                           \
-    __w.ll; })
-
-typedef         int SItype     __mode(SI);
-typedef unsigned int USItype   __mode(SI);
-typedef                 int DItype     __mode(DI);
-typedef int word_type           __mode(__word__);
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__muldi3 (DItype u, DItype v)
-{
-  DIunion w;
-  DIunion uu, vv;
-
-  uu.ll = u;
-  vv.ll = v;
-
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-              + (USItype) uu.s.high * (USItype) vv.s.low);
-
-  return w.ll;
-}
-EXPORT_SYMBOL(__muldi3);
index fc388da6a027faafe91ff3824750f45aa8121035..0d68f9d6a6a7e6548c132152cc7c5a512b5c7bec 100644 (file)
@@ -34,4 +34,8 @@ 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);
 
+#ifdef CONFIG_HAVE_ARCH_LIBGCC_H
+#include <asm/libgcc.h>
+#endif
+
 #endif /* __ASM_LIBGCC_H */