]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/libdruntime/config/powerpc/switchcontext.S
74395b04014d0b9d266c0239538035e223af6c20
[thirdparty/gcc.git] / libphobos / libdruntime / config / powerpc / switchcontext.S
1 /* PowerPC support code for fibers and multithreading.
2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 #include "../common/threadasm.S"
26
27 #if !defined(__PPC64__) && !defined(__MACH__)
28
29 /**
30 * Performs a context switch.
31 *
32 * r3 - old context pointer
33 * r4 - new context pointer
34 *
35 */
36 .text
37 .globl CSYM(fiber_switchContext)
38 .type CSYM(fiber_switchContext), @function
39 .align 2
40 CSYM(fiber_switchContext):
41 .cfi_startproc
42 /* Save linkage area */
43 mflr 0
44 mfcr 5
45 stw 0, 8(1)
46 stw 5, 4(1)
47
48 /* Save GPRs */
49 stw 11, (-1 * 4)(1)
50 stw 13, (-2 * 4)(1)
51 stw 14, (-3 * 4)(1)
52 stw 15, (-4 * 4)(1)
53 stw 16, (-5 * 4)(1)
54 stw 17, (-6 * 4)(1)
55 stw 18, (-7 * 4)(1)
56 stw 19, (-8 * 4)(1)
57 stw 20, (-9 * 4)(1)
58 stw 21, (-10 * 4)(1)
59 stw 22, (-11 * 4)(1)
60 stw 23, (-12 * 4)(1)
61 stw 24, (-13 * 4)(1)
62 stw 25, (-14 * 4)(1)
63 stw 26, (-15 * 4)(1)
64 stw 27, (-16 * 4)(1)
65 stw 28, (-17 * 4)(1)
66 stw 29, (-18 * 4)(1)
67 stw 30, (-19 * 4)(1)
68 stwu 31, (-20 * 4)(1)
69
70 /* We update the stack pointer here, since we do not want the GC to
71 scan the floating point registers. */
72
73 /* Save FPRs */
74 stfd 14, (-1 * 8)(1)
75 stfd 15, (-2 * 8)(1)
76 stfd 16, (-3 * 8)(1)
77 stfd 17, (-4 * 8)(1)
78 stfd 18, (-5 * 8)(1)
79 stfd 19, (-6 * 8)(1)
80 stfd 20, (-7 * 8)(1)
81 stfd 21, (-8 * 8)(1)
82 stfd 22, (-9 * 8)(1)
83 stfd 23, (-10 * 8)(1)
84 stfd 24, (-11 * 8)(1)
85 stfd 25, (-12 * 8)(1)
86 stfd 26, (-13 * 8)(1)
87 stfd 27, (-14 * 8)(1)
88 stfd 28, (-15 * 8)(1)
89 stfd 29, (-16 * 8)(1)
90 stfd 30, (-17 * 8)(1)
91 stfd 31, (-18 * 8)(1)
92
93 /* Update the old stack pointer */
94 stw 1, 0(3)
95
96 /* Set new stack pointer */
97 addi 1, 4, 20 * 4
98
99 /* Restore linkage area */
100 lwz 0, 8(1)
101 lwz 5, 4(1)
102
103 /* Restore GPRs */
104 lwz 11, (-1 * 4)(1)
105 lwz 13, (-2 * 4)(1)
106 lwz 14, (-3 * 4)(1)
107 lwz 15, (-4 * 4)(1)
108 lwz 16, (-5 * 4)(1)
109 lwz 17, (-6 * 4)(1)
110 lwz 18, (-7 * 4)(1)
111 lwz 19, (-8 * 4)(1)
112 lwz 20, (-9 * 4)(1)
113 lwz 21, (-10 * 4)(1)
114 lwz 22, (-11 * 4)(1)
115 lwz 23, (-12 * 4)(1)
116 lwz 24, (-13 * 4)(1)
117 lwz 25, (-14 * 4)(1)
118 lwz 26, (-15 * 4)(1)
119 lwz 27, (-16 * 4)(1)
120 lwz 28, (-17 * 4)(1)
121 lwz 29, (-18 * 4)(1)
122 lwz 30, (-19 * 4)(1)
123 lwz 31, (-20 * 4)(1)
124
125 /* Restore FPRs */
126 lfd 14, (-1 * 8)(4)
127 lfd 15, (-2 * 8)(4)
128 lfd 16, (-3 * 8)(4)
129 lfd 17, (-4 * 8)(4)
130 lfd 18, (-5 * 8)(4)
131 lfd 19, (-6 * 8)(4)
132 lfd 20, (-7 * 8)(4)
133 lfd 21, (-8 * 8)(4)
134 lfd 22, (-9 * 8)(4)
135 lfd 23, (-10 * 8)(4)
136 lfd 24, (-11 * 8)(4)
137 lfd 25, (-12 * 8)(4)
138 lfd 26, (-13 * 8)(4)
139 lfd 27, (-14 * 8)(4)
140 lfd 28, (-15 * 8)(4)
141 lfd 29, (-16 * 8)(4)
142 lfd 30, (-17 * 8)(4)
143 lfd 31, (-18 * 8)(4)
144
145 /* Set condition and link register */
146 mtcr 5
147 mtlr 0
148
149 /* Return and switch context */
150 blr
151 .cfi_endproc
152 .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
153
154 #elif defined(__MACH__)
155
156 /* Implementation for Darwin/macOS preserving callee-saved regs.
157
158 FIXME : There is no unwind frame.
159 FIXME : not sure if we should save the vsave reg (perhaps using the slot we have
160 r11 in at present). */
161
162 /* Darwin has a red zone (220 bytes for PPC 288 for PPC64) which we can write
163 to before the stack is updated without worrying about it being clobbered by
164 signals or hardware interrupts.
165
166 The stack will be 16byte aligned on entry with:
167 PPC PPC64
168 SP-> +---------------------------------------+
169 | back chain to caller | 0 0
170 +---------------------------------------+
171 | slot to save CR | 4 8
172 +---------------------------------------+
173 | slot to save LR | 8 16
174 +---------------------------------------+
175 | etc.. etc.. as per C calling conv. | */
176
177 # if __PPC64__
178 # define LD ld
179 # define ST std
180 # define STU stdu
181 # define SZ 8
182 # define MACHINE ppc64
183 # define RED_ZONE 288
184 # else
185 # define LD lwz
186 # define ST stw
187 # define STU stwu
188 # define SZ 4
189 # define MACHINE ppc7400
190 # define RED_ZONE 220
191 # endif
192
193 # define SAVE_VECTORS 0
194 /**
195 * Performs a context switch.
196 *
197 * r3 - old context pointer
198 * r4 - new context pointer
199 *
200 */
201 .machine MACHINE
202 .text
203 .globl CSYM(fiber_switchContext)
204 .align 2
205 CSYM(fiber_switchContext):
206 LFB0:
207 /* Get the link reg. */
208 mflr r0
209 /* Get the callee-saved crs (well all of them, actually). */
210 mfcr r12
211
212 /* Save GPRs, we save the static chain here too although it is not clear if we need to. */
213 ST r31, ( -1 * SZ)(r1)
214 ST r30, ( -2 * SZ)(r1)
215 ST r29, ( -3 * SZ)(r1)
216 ST r28, ( -4 * SZ)(r1)
217 ST r27, ( -5 * SZ)(r1)
218 ST r26, ( -6 * SZ)(r1)
219 ST r25, ( -7 * SZ)(r1)
220 ST r24, ( -8 * SZ)(r1)
221 ST r23, ( -9 * SZ)(r1)
222 ST r22, (-10 * SZ)(r1)
223 ST r21, (-11 * SZ)(r1)
224 ST r20, (-12 * SZ)(r1)
225 ST r19, (-13 * SZ)(r1)
226 ST r18, (-14 * SZ)(r1)
227 ST r17, (-15 * SZ)(r1)
228 ST r16, (-16 * SZ)(r1)
229 ST r15, (-17 * SZ)(r1)
230 ST r14, (-18 * SZ)(r1)
231 ST r13, (-19 * SZ)(r1)
232
233 /* Save the lr and cr into the normal function linkage area. */
234 ST r0, 2*SZ(r1)
235 ST r12, SZ(r1)
236
237 /* We update the stack pointer here, since we do not want the GC to
238 scan the floating point registers. We are still 16-byte aligned. */
239 STU r11, (-20 * SZ)(r1)
240
241 /* Update the stack pointer in the old context as per comment above. */
242 ST r1, 0(r3)
243
244 /* Save FPRs - same for PPC and PPC64 */
245 stfd f14, (-18 * 8)(r1)
246 stfd f15, (-17 * 8)(r1)
247 stfd f16, (-16 * 8)(r1)
248 stfd f17, (-15 * 8)(r1)
249 stfd f18, (-14 * 8)(r1)
250 stfd f19, (-13 * 8)(r1)
251 stfd f20, (-12 * 8)(r1)
252 stfd f21, (-11 * 8)(r1)
253 stfd f22, (-10 * 8)(r1)
254 stfd f23, ( -9 * 8)(r1)
255 stfd f24, ( -8 * 8)(r1)
256 stfd f25, ( -7 * 8)(r1)
257 stfd f26, ( -6 * 8)(r1)
258 stfd f27, ( -5 * 8)(r1)
259 stfd f28, ( -4 * 8)(r1)
260 stfd f29, ( -3 * 8)(r1)
261 stfd f30, ( -2 * 8)(r1)
262 stfd f31, ( -1 * 8)(r1)
263
264 #if SAVE_VECTORS
265 /* We are still 16byte aligned - so we are ok for vector saves.
266 but the combined size of the vectors (12 x 16) + the FPRs (144) exceeds the
267 red zone size so we need to adjust the stack again - note this means careful
268 ordering is needed on the restore. */
269
270 addi r1, r1, -(12*16+18*8)
271 li r11, 0
272 stvx v20,r11,r1
273 addi r11, r11, 16
274 stvx v21,r11,r1
275 addi r11, r11, 16
276 stvx v22,r11,r1
277 addi r11, r11, 16
278 stvx v23,r11,r1
279 addi r11, r11, 16
280 stvx v24,r11,r1
281 addi r11, r11, 16
282 stvx v25,r11,r1
283 addi r11, r11, 16
284 stvx v26,r11,r1
285 addi r11, r11, 16
286 stvx v27,r11,r1
287 addi r11, r11, 16
288 stvx v28,r11,r1
289 addi r11, r11, 16
290 stvx v29,r11,r1
291 addi r11, r11, 16
292 stvx v30,r11,r1
293 addi r11, r11, 16
294 stvx v31,r11,r1
295
296 /* Now do the same thing in reverse - starting with r4 pointing to
297 the block of GPRs - stage 1 point to the saved vectors and fprs. */
298
299 addi r1, r4, -(12*16+18*8)
300 li r11, 0
301 lvx v20,r11,r1
302 addi r11, r11, 16
303 lvx v21,r11,r1
304 addi r11, r11, 16
305 lvx v22,r11,r1
306 addi r11, r11, 16
307 lvx v23,r11,r1
308 addi r11, r11, 16
309 lvx v24,r11,r1
310 addi r11, r11, 16
311 lvx v25,r11,r1
312 addi r11, r11, 16
313 lvx v26,r11,r1
314 addi r11, r11, 16
315 lvx v27,r11,r1
316 addi r11, r11, 16
317 lvx v28,r11,r1
318 addi r11, r11, 16
319 lvx v29,r11,r1
320 addi r11, r11, 16
321 lvx v30,r11,r1
322 addi r11, r11, 16
323 lvx v31,r11,r1
324 #endif
325
326 /* Now it is safe to update the stack pointer since the combined
327 size of the GPRs and FPRs will not exceed the red zone. */
328
329 addi r1, r4, 20 * SZ
330
331 /* Restore FPRs */
332 lfd f14, (-18 * 8)(r4)
333 lfd f15, (-17 * 8)(r4)
334 lfd f16, (-16 * 8)(r4)
335 lfd f17, (-15 * 8)(r4)
336 lfd f18, (-14 * 8)(r4)
337 lfd f19, (-13 * 8)(r4)
338 lfd f20, (-12 * 8)(r4)
339 lfd f21, (-11 * 8)(r4)
340 lfd f22, (-10 * 8)(r4)
341 lfd f23, ( -9 * 8)(r4)
342 lfd f24, ( -8 * 8)(r4)
343 lfd f25, ( -7 * 8)(r4)
344 lfd f26, ( -6 * 8)(r4)
345 lfd f27, ( -5 * 8)(r4)
346 lfd f28, ( -4 * 8)(r4)
347 lfd f29, ( -3 * 8)(r4)
348 lfd f30, ( -2 * 8)(r4)
349 lfd f31, ( -1 * 8)(r4)
350
351 /* Pick up lr and cr */
352 LD r0, 2*SZ(r1)
353 LD r12, SZ(r1)
354
355 /* Restore GPRs */
356 LD r11, (-20 * SZ)(r1)
357 LD r13, (-19 * SZ)(r1)
358 LD r14, (-18 * SZ)(r1)
359 LD r15, (-17 * SZ)(r1)
360 LD r16, (-16 * SZ)(r1)
361 LD r17, (-15 * SZ)(r1)
362 LD r18, (-14 * SZ)(r1)
363 LD r19, (-13 * SZ)(r1)
364 LD r20, (-12 * SZ)(r1)
365 LD r21, (-11 * SZ)(r1)
366 LD r22, (-10 * SZ)(r1)
367 LD r23, ( -9 * SZ)(r1)
368 LD r24, ( -8 * SZ)(r1)
369 LD r25, ( -7 * SZ)(r1)
370 LD r26, ( -6 * SZ)(r1)
371 LD r27, ( -5 * SZ)(r1)
372 LD r28, ( -4 * SZ)(r1)
373 LD r29, ( -3 * SZ)(r1)
374 LD r30, ( -2 * SZ)(r1)
375 LD r31, ( -1 * SZ)(r1)
376
377 /* Set cr and lr */
378 mtcr r12
379 mtlr r0
380
381 /* Return and switch context */
382 blr
383 LFE0:
384
385 /* Minimal CFI / FDE which does not describe the stacking of the GPRs - but only that
386 the routine has been entered/exited. */
387
388 # if __PPC64__
389 # define DATA_ALIGN 0x78
390 # define ALIGN_SIZE 3
391 # define ADDRD .quad
392 # else
393 # define DATA_ALIGN 0x7c
394 # define ALIGN_SIZE 3
395 # define ADDRD .long
396 # endif
397
398 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
399 EH_frame1:
400 .set L$set$0,LECIE1-LSCIE1
401 .long L$set$0 ; Length of Common Information Entry
402 LSCIE1:
403 .long 0 ; CIE Identifier Tag
404 .byte 0x3 ; CIE Version
405 .ascii "zR\0" ; CIE Augmentation
406 .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
407 .byte DATA_ALIGN ; sleb128 -4/-8; CIE Data Alignment Factor
408 .byte 0x41 ; uleb128 0x41; CIE RA Column
409 .byte 0x1 ; uleb128 0x1; Augmentation size
410 .byte 0x10 ; FDE Encoding (pcrel)
411 .byte 0xc ; DW_CFA_def_cfa
412 .byte 0x1 ; uleb128 0x1
413 .byte 0 ; uleb128 0
414 .p2align ALIGN_SIZE,0
415 LECIE1:
416 LSFDE1:
417 .set L$set$1,LEFDE1-LASFDE1
418 .long L$set$1 ; FDE Length
419 LASFDE1:
420 .long LASFDE1-EH_frame1 ; FDE CIE offset
421 ADDRD LFB0-. ; FDE initial location
422 .set L$set$2,LFE0-LFB0
423 ADDRD L$set$2 ; FDE address range
424 .byte 0 ; uleb128 0; Augmentation size
425 .p2align ALIGN_SIZE,0
426 LEFDE1:
427
428 #endif /* defined(__MACH__) */