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 <[email protected]> --- 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([email protected]): 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

