Hi Daniel,

On Wed, Mar 11, 2026 at 06:30:48PM +0900, Daniel Palmer wrote:
> 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

Maybe add a comment saying why we must drop --gc-sections when both LTO
and private libgcc are enabled?

> +
> +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);

I guess you mean arch_setup_gd(gd_ptr) here?

>  
>       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));

We have __used in linux/compiler.h, which I think is preferred over raw
__attribute__((used)).

Regards,
Kuan-Wei

>  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
> 

Reply via email to