1 /* Assembly macros for 32-bit PowerPC.
2    Copyright (C) 1999-2021 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	;					      \
52 GOT_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 #if defined SHARED && defined PIC && !defined NO_HIDDEN
108 # undef HIDDEN_JUMPTARGET
109 # define HIDDEN_JUMPTARGET(name) __GI_##name##@local
110 #endif
111 
112 #define TAIL_CALL_SYSCALL_ERROR \
113     b __syscall_error@local
114 
115 #define PSEUDO(name, syscall_name, args)				      \
116   .section ".text";							      \
117   ENTRY (name)								      \
118     DO_CALL (SYS_ify (syscall_name));
119 
120 #define RET_SC \
121     bnslr+;
122 
123 #define PSEUDO_RET							      \
124     RET_SC;								      \
125     TAIL_CALL_SYSCALL_ERROR
126 #define ret PSEUDO_RET
127 
128 #undef	PSEUDO_END
129 #define	PSEUDO_END(name)						      \
130   END (name)
131 
132 #define PSEUDO_NOERRNO(name, syscall_name, args)			      \
133   .section ".text";							      \
134   ENTRY (name)								      \
135     DO_CALL (SYS_ify (syscall_name));
136 
137 #define PSEUDO_RET_NOERRNO						      \
138     blr
139 #define ret_NOERRNO PSEUDO_RET_NOERRNO
140 
141 #undef	PSEUDO_END_NOERRNO
142 #define	PSEUDO_END_NOERRNO(name)					      \
143   END (name)
144 
145 #define PSEUDO_ERRVAL(name, syscall_name, args)				      \
146   .section ".text";							      \
147   ENTRY (name)								      \
148     DO_CALL (SYS_ify (syscall_name));
149 
150 #define PSEUDO_RET_ERRVAL						      \
151     blr
152 #define ret_ERRVAL PSEUDO_RET_ERRVAL
153 
154 #undef	PSEUDO_END_ERRVAL
155 #define	PSEUDO_END_ERRVAL(name)						      \
156   END (name)
157 
158 /* Local labels stripped out by the linker.  */
159 #undef L
160 #define L(x) .L##x
161 
162 #define XGLUE(a,b) a##b
163 #define GLUE(a,b) XGLUE (a,b)
164 #define GENERATE_GOT_LABEL(name) GLUE (.got_label, name)
165 
166 /* Label in text section.  */
167 #define C_TEXT(name) name
168 
169 /* Read the value of member from rtld_global_ro.  */
170 #ifdef PIC
171 # ifdef SHARED
172 #  if IS_IN (rtld)
173 /* Inside ld.so we use the local alias to avoid runtime GOT
174    relocations.  */
175 #   define __GLRO(rOUT, rGOT, member, offset)				\
176 	lwz     rOUT,_rtld_local_ro@got(rGOT);				\
177 	lwz     rOUT,offset(rOUT)
178 #  else
179 #   define __GLRO(rOUT, rGOT, member, offset)				\
180 	lwz     rOUT,_rtld_global_ro@got(rGOT);				\
181 	lwz     rOUT,offset(rOUT)
182 #  endif
183 # else
184 #  define __GLRO(rOUT, rGOT, member, offset)				\
185 	lwz     rOUT,member@got(rGOT);					\
186 	lwz     rOUT,0(rOUT)
187 # endif
188 #else
189 /* Position-dependent code does not require access to the GOT.  */
190 # define __GLRO(rOUT, rGOT, member, offset)				\
191 	lis     rOUT,(member)@ha;					\
192 	lwz     rOUT,(member)@l(rOUT)
193 #endif	/* PIC */
194 
195 #endif	/* __ASSEMBLER__ */
196