1/* Assembly macros for 32-bit PowerPC.
  2   Copyright (C) 1999-2025 Free Software Foundation, Inc.
  3   This file is part of the GNU C Library.
  4
  5   The GNU C Library is free software; you can redistribute it and/or
  6   modify it under the terms of the GNU Lesser General Public
  7   License as published by the Free Software Foundation; either
  8   version 2.1 of the License, or (at your option) any later version.
  9
 10   The GNU C Library is distributed in the hope that it will be useful,
 11   but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13   Lesser General Public License for more details.
 14
 15   You should have received a copy of the GNU Lesser General Public
 16   License along with the GNU C Library; if not, see
 17   <https://www.gnu.org/licenses/>.  */
 18
 19#include <sysdeps/powerpc/sysdep.h>
 20
 21#ifdef __ASSEMBLER__
 22
 23/* If compiled for profiling, call `_mcount' at the start of each
 24   function.  */
 25#ifdef	PROF
 26/* The mcount code relies on a the return address being on the stack
 27   to locate our caller and so it can restore it; so store one just
 28   for its benefit.  */
 29# define CALL_MCOUNT							      \
 30  mflr  r0;								      \
 31  stw   r0,4(r1);							      \
 32  cfi_offset (lr, 4);							      \
 33  bl    JUMPTARGET(_mcount);
 34#else  /* PROF */
 35# define CALL_MCOUNT		/* Do nothing.  */
 36#endif /* PROF */
 37
 38#define	ENTRY(name)							      \
 39  .globl C_SYMBOL_NAME(name);						      \
 40  .type C_SYMBOL_NAME(name),@function;					      \
 41  .align ALIGNARG(2);							      \
 42  C_LABEL(name)								      \
 43  cfi_startproc;							      \
 44  CALL_MCOUNT
 45
 46#define ENTRY_TOCLESS(name) ENTRY(name)
 47
 48/* helper macro for accessing the 32-bit powerpc GOT. */
 49
 50#define	SETUP_GOT_ACCESS(regname,GOT_LABEL)				      \
 51	bcl	20,31,GOT_LABEL	;					      \
 52GOT_LABEL:			;					      \
 53	mflr	(regname)
 54
 55#define EALIGN_W_0  /* No words to insert.  */
 56#define EALIGN_W_1  nop
 57#define EALIGN_W_2  nop;nop
 58#define EALIGN_W_3  nop;nop;nop
 59#define EALIGN_W_4  EALIGN_W_3;nop
 60#define EALIGN_W_5  EALIGN_W_4;nop
 61#define EALIGN_W_6  EALIGN_W_5;nop
 62#define EALIGN_W_7  EALIGN_W_6;nop
 63
 64/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
 65   past a 2^align boundary.  */
 66#ifdef PROF
 67# define EALIGN(name, alignt, words)					      \
 68  .globl C_SYMBOL_NAME(name);						      \
 69  .type C_SYMBOL_NAME(name),@function;					      \
 70  .align ALIGNARG(2);							      \
 71  C_LABEL(name)								      \
 72  cfi_startproc;							      \
 73  CALL_MCOUNT								      \
 74  b 0f;									      \
 75  .align ALIGNARG(alignt);						      \
 76  EALIGN_W_##words;							      \
 77  0:
 78#else /* PROF */
 79# define EALIGN(name, alignt, words)					      \
 80  .globl C_SYMBOL_NAME(name);						      \
 81  .type C_SYMBOL_NAME(name),@function;					      \
 82  .align ALIGNARG(alignt);						      \
 83  EALIGN_W_##words;							      \
 84  C_LABEL(name)								      \
 85  cfi_startproc;
 86#endif
 87
 88#undef	END
 89#define END(name)							      \
 90  cfi_endproc;								      \
 91  ASM_SIZE_DIRECTIVE(name)
 92
 93#define DO_CALL(syscall)						      \
 94    li 0,syscall;							      \
 95    DO_CALL_SC
 96
 97#define DO_CALL_SC \
 98	sc
 99
100#undef JUMPTARGET
101#ifdef PIC
102# define JUMPTARGET(name) name##@plt
103#else
104# define JUMPTARGET(name) name
105#endif
106
107#define TAIL_CALL_NO_RETURN(__func) \
108    b __func@local
109
110#if defined SHARED && defined PIC && !defined NO_HIDDEN
111# undef HIDDEN_JUMPTARGET
112# define HIDDEN_JUMPTARGET(name) __GI_##name##@local
113#endif
114
115#define TAIL_CALL_SYSCALL_ERROR \
116    b __syscall_error@local
117
118#define PSEUDO(name, syscall_name, args)				      \
119  .section ".text";							      \
120  ENTRY (name)								      \
121    DO_CALL (SYS_ify (syscall_name));
122
123#define RET_SC \
124    bnslr+;
125
126#define PSEUDO_RET							      \
127    RET_SC;								      \
128    TAIL_CALL_SYSCALL_ERROR
129#define ret PSEUDO_RET
130
131#undef	PSEUDO_END
132#define	PSEUDO_END(name)						      \
133  END (name)
134
135#define PSEUDO_NOERRNO(name, syscall_name, args)			      \
136  .section ".text";							      \
137  ENTRY (name)								      \
138    DO_CALL (SYS_ify (syscall_name));
139
140#define PSEUDO_RET_NOERRNO						      \
141    blr
142#define ret_NOERRNO PSEUDO_RET_NOERRNO
143
144#undef	PSEUDO_END_NOERRNO
145#define	PSEUDO_END_NOERRNO(name)					      \
146  END (name)
147
148#define PSEUDO_ERRVAL(name, syscall_name, args)				      \
149  .section ".text";							      \
150  ENTRY (name)								      \
151    DO_CALL (SYS_ify (syscall_name));
152
153#define PSEUDO_RET_ERRVAL						      \
154    blr
155#define ret_ERRVAL PSEUDO_RET_ERRVAL
156
157#undef	PSEUDO_END_ERRVAL
158#define	PSEUDO_END_ERRVAL(name)						      \
159  END (name)
160
161/* Local labels stripped out by the linker.  */
162#undef L
163#define L(x) .L##x
164
165#define XGLUE(a,b) a##b
166#define GLUE(a,b) XGLUE (a,b)
167#define GENERATE_GOT_LABEL(name) GLUE (.got_label, name)
168
169/* Label in text section.  */
170#define C_TEXT(name) name
171
172/* Read the value of member from rtld_global_ro.  */
173#ifdef PIC
174# ifdef SHARED
175#  if IS_IN (rtld)
176/* Inside ld.so we use the local alias to avoid runtime GOT
177   relocations.  */
178#   define __GLRO(rOUT, rGOT, member, offset)				\
179	lwz     rOUT,_rtld_local_ro@got(rGOT);				\
180	lwz     rOUT,offset(rOUT)
181#  else
182#   define __GLRO(rOUT, rGOT, member, offset)				\
183	lwz     rOUT,_rtld_global_ro@got(rGOT);				\
184	lwz     rOUT,offset(rOUT)
185#  endif
186# else
187#  define __GLRO(rOUT, rGOT, member, offset)				\
188	lwz     rOUT,member@got(rGOT);					\
189	lwz     rOUT,0(rOUT)
190# endif
191#else
192/* Position-dependent code does not require access to the GOT.  */
193# define __GLRO(rOUT, rGOT, member, offset)				\
194	lis     rOUT,(member)@ha;					\
195	lwz     rOUT,(member)@l(rOUT)
196#endif	/* PIC */
197
198#endif	/* __ASSEMBLER__ */