[PATCH] m68k: Add LTO support

Daniel Palmer daniel at thingy.jp
Wed Mar 11 10:30:48 CET 2026


Most m68k retro/homebrew machines will have limited flash/RAM
so having LTO working would be nice.

Not many changes are need really. Most of this is copy/paste
from the ARM32 version.

The major change is that the direct register usage of d7 for gd
needs to be hidden so that when LTO passes over everything it
doesn't see multiple instances of d7.

Signed-off-by: Daniel Palmer <daniel at thingy.jp>
---

This is another patch from my vault that I have been using
on various classic m68k machines for ages. I haven't tested
it with coldfire though.

 arch/Kconfig                        |  1 +
 arch/m68k/config.mk                 | 11 +++++++++--
 arch/m68k/cpu/m680x0/cpu.c          |  2 +-
 arch/m68k/include/asm/global_data.h | 19 +++++++++++++++++++
 arch/m68k/lib/ashldi3.c             |  1 +
 arch/m68k/lib/lshrdi3.c             |  1 +
 arch/m68k/lib/muldi3.c              |  1 +
 common/board_r.c                    |  4 ++--
 common/init/board_init.c            |  2 +-
 9 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 4af0da2485fb..488de442f557 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -112,6 +112,7 @@ config ARM
 
 config M68K
 	bool "M68000 architecture"
+	select ARCH_SUPPORTS_LTO
 	select HAVE_PRIVATE_LIBGCC
 	select USE_PRIVATE_LIBGCC
 	select SYS_BOOT_GET_CMDLINE
diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk
index 458953f97122..1be46adda966 100644
--- a/arch/m68k/config.mk
+++ b/arch/m68k/config.mk
@@ -8,9 +8,16 @@ ifneq ($(CONFIG_M680x0),y)
 PLATFORM_CPPFLAGS += -fPIC
 endif
 KBUILD_LDFLAGS    += -n -pie
-PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
 PLATFORM_RELFLAGS += -ffixed-d7
 ifneq ($(CONFIG_M680x0),y)
 PLATFORM_RELFLAGS += -msep-data
 endif
-LDFLAGS_FINAL     += --gc-sections -pie
+LDFLAGS_FINAL     += -pie
+
+ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
+LDFLAGS_FINAL     += --gc-sections
+endif
+
+ifneq ($(LTO_ENABLE),y)
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+endif
diff --git a/arch/m68k/cpu/m680x0/cpu.c b/arch/m68k/cpu/m680x0/cpu.c
index f60b932c7dd4..3f87076b8c3d 100644
--- a/arch/m68k/cpu/m680x0/cpu.c
+++ b/arch/m68k/cpu/m680x0/cpu.c
@@ -24,7 +24,7 @@ void m68k_virt_init_reserve(ulong base)
 	for (i = 0; i < sizeof(*gd_ptr); i++)
 		p[i] = 0;
 
-	gd = gd_ptr;
+	arch_setup_gd(gd);
 
 	gd->malloc_base = base + sizeof(*gd_ptr);
 }
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index aea2ccabe083..9150ed4ab466 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -32,6 +32,25 @@ struct arch_global_data {
 
 #include <asm-generic/global_data.h>
 
+#if defined(LTO_ENABLE)
+/* If LTO is enabled we have to hide d7 to avoid multiple symbol declarations */
+#define DECLARE_GLOBAL_DATA_PTR
+#define gd	get_gd()
+
+static inline gd_t *get_gd(void)
+{
+	gd_t *gd_ptr;
+
+	__asm__ volatile("move.l %%d7, %0\n" : "=r" (gd_ptr));
+
+	return gd_ptr;
+}
+#else
 #define DECLARE_GLOBAL_DATA_PTR     register gd_t *gd asm ("d7")
+#endif
+static inline void arch_setup_gd(gd_t *new_gd)
+{
+	__asm__ volatile("move.l %0, %%d7\n" : : "r" (new_gd));
+}
 
 #endif /* __ASM_GBL_DATA_H */
diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c
index 9a4bc676bf4c..82bd9113ecbf 100644
--- a/arch/m68k/lib/ashldi3.c
+++ b/arch/m68k/lib/ashldi3.c
@@ -21,6 +21,7 @@ typedef union
   DItype ll;
 } DIunion;
 
+DItype __ashldi3 (DItype u, word_type b) __attribute__((used));
 DItype __ashldi3 (DItype u, word_type b)
 {
 	DIunion w;
diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c
index e639e676a269..691d503d7313 100644
--- a/arch/m68k/lib/lshrdi3.c
+++ b/arch/m68k/lib/lshrdi3.c
@@ -21,6 +21,7 @@ typedef union
   DItype ll;
 } DIunion;
 
+DItype __lshrdi3 (DItype u, word_type b) __attribute__((used));
 DItype __lshrdi3 (DItype u, word_type b)
 {
 	DIunion w;
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
index c42ca1d753e5..53d674701531 100644
--- a/arch/m68k/lib/muldi3.c
+++ b/arch/m68k/lib/muldi3.c
@@ -54,6 +54,7 @@ typedef union
 	DItype ll;
 } DIunion;
 
+DItype __muldi3 (DItype u, DItype v) __attribute__((used));
 DItype __muldi3 (DItype u, DItype v)
 {
 	DIunion w;
diff --git a/common/board_r.c b/common/board_r.c
index 76f9fc090fbe..58eb69005468 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -800,12 +800,12 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
 	 * TODO(sjg at chromium.org): Consider doing this for all archs, or
 	 * dropping the new_gd parameter.
 	 */
-	if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
+	if ((CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP)) || CONFIG_IS_ENABLED(M68K))
 		arch_setup_gd(new_gd);
 
 #if defined(CONFIG_RISCV)
 	set_gd(new_gd);
-#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) && !defined(CONFIG_M68K)
 	gd = new_gd;
 #endif
 	gd->flags &= ~GD_FLG_LOG_READY;
diff --git a/common/init/board_init.c b/common/init/board_init.c
index 2a6f39f51adb..c56b33e7be7c 100644
--- a/common/init/board_init.c
+++ b/common/init/board_init.c
@@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
  * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
  * as macro and cannot be assigned.
  */
-#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) && !defined(CONFIG_M68K)
 __weak void arch_setup_gd(struct global_data *gd_ptr)
 {
 	gd = gd_ptr;
-- 
2.51.0



More information about the U-Boot mailing list