On 18 October 2026 09:35:05 BST, Josef Schlehofer
<[email protected]> wrote:
>When GCC optimizes for size, it branches to libgcc's _restgpr_N_x
>routines to restore non-volatile registers. U-Boot's private libgcc
>lacks these routines, so builds with CONFIG_USE_PRIVATE_LIBGCC=y fail
>to link with Debian's GCC 14.2, for example qemu-ppce500:
>
>  undefined reference to `_restgpr_31_x'
>
>Copy the 32-bit integer register save and restore routines from
>Linux's arch/powerpc/lib/crtsavres.S (v7.3-rc5), following the private
>libgcc's existing approach for shift routines. Put each group of
>routines in its own section so --gc-sections can discard unused
>groups. Linux's CONFIG_CC_OPTIMIZE_FOR_SIZE condition is then not
>needed.
>
>Signed-off-by: Josef Schlehofer <[email protected]>
>Cc: Tom Rini <[email protected]>
>Cc: Christophe Leroy <[email protected]>
>Cc: Marek BehĂșn <[email protected]>
>---
>Changes in v2:
>- new patch
>
>The routines assemble to the same code as crtsavgpr.o, crtresgpr.o and
>crtresxgpr.o in Debian's libgcc 14.2.
>---
> arch/powerpc/lib/Makefile    |   3 +-
> arch/powerpc/lib/crtsavres.S | 213 +++++++++++++++++++++++++++++++++++
> 2 files changed, 215 insertions(+), 1 deletion(-)
> create mode 100644 arch/powerpc/lib/crtsavres.S

I feel a maintainers entry for this would be good, or could it be covered
under me? (If I end up getting maintainers patch merged)


>
>diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
>index a3048975ae7..90f0e1e5fa9 100644
>--- a/arch/powerpc/lib/Makefile
>+++ b/arch/powerpc/lib/Makefile
>@@ -5,7 +5,8 @@
> 
> ## Build a couple of necessary functions into a private libgcc
> ## if the user asked for it
>-lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _lshrdi3.o
>+lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _lshrdi3.o \
>+                                  crtsavres.o
> 
> MINIMAL=
> 
>diff --git a/arch/powerpc/lib/crtsavres.S b/arch/powerpc/lib/crtsavres.S
>new file mode 100644
>index 00000000000..8c35eedecb6
>--- /dev/null
>+++ b/arch/powerpc/lib/crtsavres.S
>@@ -0,0 +1,213 @@
>+/* SPDX-License-Identifier: GPL-2.0+ */
>+/*
>+ * Out-of-line integer register save and restore routines, which GCC calls
>+ * from function prologues and epilogues when it optimizes for size.
>+ *
>+ * This code was copied from crtsavres.S in arch/powerpc/lib of the Linux
>+ * kernel sources (v7.3-rc5, last changed by commit 699d53f04829
>+ * ("powerpc/vdso32: Fix use of crtsavres for PPC64")): the 32-bit integer
>+ * register routines, without the CONFIG_CC_OPTIMIZE_FOR_SIZE condition.
>+ * Each group of routines is in a section of its own, so that --gc-sections
>+ * drops the groups that nothing calls. The source file copyrights are as
>+ * follows:
>+ *
>+ *   Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
>+ *   Copyright 2008 Freescale Semiconductor, Inc.
>+ *   Written By Michael Meissner
>+ *
>+ * Based on gcc/config/rs6000/crtsavres.asm from gcc
>+ */
>+
>+#include <asm/processor.h>
>+
>+/* Routines for saving integer registers, called by the compiler.  */
>+/* Called with r11 pointing to the stack header word of the caller of the */
>+/* function, just beyond the end of the integer save area.  */
>+
>+      .section ".text._savegpr_14","ax",@progbits
>+      .align  2
>+
>+_GLOBAL(_savegpr_14)
>+_GLOBAL(_save32gpr_14)
>+      stw     14,-72(11)      /* save gp registers */
>+_GLOBAL(_savegpr_15)
>+_GLOBAL(_save32gpr_15)
>+      stw     15,-68(11)
>+_GLOBAL(_savegpr_16)
>+_GLOBAL(_save32gpr_16)
>+      stw     16,-64(11)
>+_GLOBAL(_savegpr_17)
>+_GLOBAL(_save32gpr_17)
>+      stw     17,-60(11)
>+_GLOBAL(_savegpr_18)
>+_GLOBAL(_save32gpr_18)
>+      stw     18,-56(11)
>+_GLOBAL(_savegpr_19)
>+_GLOBAL(_save32gpr_19)
>+      stw     19,-52(11)
>+_GLOBAL(_savegpr_20)
>+_GLOBAL(_save32gpr_20)
>+      stw     20,-48(11)
>+_GLOBAL(_savegpr_21)
>+_GLOBAL(_save32gpr_21)
>+      stw     21,-44(11)
>+_GLOBAL(_savegpr_22)
>+_GLOBAL(_save32gpr_22)
>+      stw     22,-40(11)
>+_GLOBAL(_savegpr_23)
>+_GLOBAL(_save32gpr_23)
>+      stw     23,-36(11)
>+_GLOBAL(_savegpr_24)
>+_GLOBAL(_save32gpr_24)
>+      stw     24,-32(11)
>+_GLOBAL(_savegpr_25)
>+_GLOBAL(_save32gpr_25)
>+      stw     25,-28(11)
>+_GLOBAL(_savegpr_26)
>+_GLOBAL(_save32gpr_26)
>+      stw     26,-24(11)
>+_GLOBAL(_savegpr_27)
>+_GLOBAL(_save32gpr_27)
>+      stw     27,-20(11)
>+_GLOBAL(_savegpr_28)
>+_GLOBAL(_save32gpr_28)
>+      stw     28,-16(11)
>+_GLOBAL(_savegpr_29)
>+_GLOBAL(_save32gpr_29)
>+      stw     29,-12(11)
>+_GLOBAL(_savegpr_30)
>+_GLOBAL(_save32gpr_30)
>+      stw     30,-8(11)
>+_GLOBAL(_savegpr_31)
>+_GLOBAL(_save32gpr_31)
>+      stw     31,-4(11)
>+      blr
>+
>+/* Routines for restoring integer registers, called by the compiler.  */
>+/* Called with r11 pointing to the stack header word of the caller of the */
>+/* function, just beyond the end of the integer restore area.  */
>+
>+      .section ".text._restgpr_14","ax",@progbits
>+      .align  2
>+
>+_GLOBAL(_restgpr_14)
>+_GLOBAL(_rest32gpr_14)
>+      lwz     14,-72(11)      /* restore gp registers */
>+_GLOBAL(_restgpr_15)
>+_GLOBAL(_rest32gpr_15)
>+      lwz     15,-68(11)
>+_GLOBAL(_restgpr_16)
>+_GLOBAL(_rest32gpr_16)
>+      lwz     16,-64(11)
>+_GLOBAL(_restgpr_17)
>+_GLOBAL(_rest32gpr_17)
>+      lwz     17,-60(11)
>+_GLOBAL(_restgpr_18)
>+_GLOBAL(_rest32gpr_18)
>+      lwz     18,-56(11)
>+_GLOBAL(_restgpr_19)
>+_GLOBAL(_rest32gpr_19)
>+      lwz     19,-52(11)
>+_GLOBAL(_restgpr_20)
>+_GLOBAL(_rest32gpr_20)
>+      lwz     20,-48(11)
>+_GLOBAL(_restgpr_21)
>+_GLOBAL(_rest32gpr_21)
>+      lwz     21,-44(11)
>+_GLOBAL(_restgpr_22)
>+_GLOBAL(_rest32gpr_22)
>+      lwz     22,-40(11)
>+_GLOBAL(_restgpr_23)
>+_GLOBAL(_rest32gpr_23)
>+      lwz     23,-36(11)
>+_GLOBAL(_restgpr_24)
>+_GLOBAL(_rest32gpr_24)
>+      lwz     24,-32(11)
>+_GLOBAL(_restgpr_25)
>+_GLOBAL(_rest32gpr_25)
>+      lwz     25,-28(11)
>+_GLOBAL(_restgpr_26)
>+_GLOBAL(_rest32gpr_26)
>+      lwz     26,-24(11)
>+_GLOBAL(_restgpr_27)
>+_GLOBAL(_rest32gpr_27)
>+      lwz     27,-20(11)
>+_GLOBAL(_restgpr_28)
>+_GLOBAL(_rest32gpr_28)
>+      lwz     28,-16(11)
>+_GLOBAL(_restgpr_29)
>+_GLOBAL(_rest32gpr_29)
>+      lwz     29,-12(11)
>+_GLOBAL(_restgpr_30)
>+_GLOBAL(_rest32gpr_30)
>+      lwz     30,-8(11)
>+_GLOBAL(_restgpr_31)
>+_GLOBAL(_rest32gpr_31)
>+      lwz     31,-4(11)
>+      blr
>+
>+/* Routines for restoring integer registers, called by the compiler.  */
>+/* Called with r11 pointing to the stack header word of the caller of the */
>+/* function, just beyond the end of the integer restore area.  */
>+
>+      .section ".text._restgpr_14_x","ax",@progbits
>+      .align  2
>+
>+_GLOBAL(_restgpr_14_x)
>+_GLOBAL(_rest32gpr_14_x)
>+      lwz     14,-72(11)      /* restore gp registers */
>+_GLOBAL(_restgpr_15_x)
>+_GLOBAL(_rest32gpr_15_x)
>+      lwz     15,-68(11)
>+_GLOBAL(_restgpr_16_x)
>+_GLOBAL(_rest32gpr_16_x)
>+      lwz     16,-64(11)
>+_GLOBAL(_restgpr_17_x)
>+_GLOBAL(_rest32gpr_17_x)
>+      lwz     17,-60(11)
>+_GLOBAL(_restgpr_18_x)
>+_GLOBAL(_rest32gpr_18_x)
>+      lwz     18,-56(11)
>+_GLOBAL(_restgpr_19_x)
>+_GLOBAL(_rest32gpr_19_x)
>+      lwz     19,-52(11)
>+_GLOBAL(_restgpr_20_x)
>+_GLOBAL(_rest32gpr_20_x)
>+      lwz     20,-48(11)
>+_GLOBAL(_restgpr_21_x)
>+_GLOBAL(_rest32gpr_21_x)
>+      lwz     21,-44(11)
>+_GLOBAL(_restgpr_22_x)
>+_GLOBAL(_rest32gpr_22_x)
>+      lwz     22,-40(11)
>+_GLOBAL(_restgpr_23_x)
>+_GLOBAL(_rest32gpr_23_x)
>+      lwz     23,-36(11)
>+_GLOBAL(_restgpr_24_x)
>+_GLOBAL(_rest32gpr_24_x)
>+      lwz     24,-32(11)
>+_GLOBAL(_restgpr_25_x)
>+_GLOBAL(_rest32gpr_25_x)
>+      lwz     25,-28(11)
>+_GLOBAL(_restgpr_26_x)
>+_GLOBAL(_rest32gpr_26_x)
>+      lwz     26,-24(11)
>+_GLOBAL(_restgpr_27_x)
>+_GLOBAL(_rest32gpr_27_x)
>+      lwz     27,-20(11)
>+_GLOBAL(_restgpr_28_x)
>+_GLOBAL(_rest32gpr_28_x)
>+      lwz     28,-16(11)
>+_GLOBAL(_restgpr_29_x)
>+_GLOBAL(_rest32gpr_29_x)
>+      lwz     29,-12(11)
>+_GLOBAL(_restgpr_30_x)
>+_GLOBAL(_rest32gpr_30_x)
>+      lwz     30,-8(11)
>+_GLOBAL(_restgpr_31_x)
>+_GLOBAL(_rest32gpr_31_x)
>+      lwz     0,4(11)
>+      lwz     31,-4(11)
>+      mtlr    0
>+      mr      1,11
>+      blr
>


Hmm. Makes sense. 

Reviewed-by: Bradley Morgan <[email protected]>


--- Thanks!
"I'm not a very positive person" - Linus torvalds

Reply via email to