1 /* PowerPC support code for fibers and multithreading.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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.
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/>. */
25 #include "../common/threadasm.S"
27 #if !defined(__PPC64__) && !defined(__MACH__)
30 * Performs a context switch.
32 * r3 - old context pointer
33 * r4 - new context pointer
37 .globl CSYM(fiber_switchContext)
38 .type CSYM(fiber_switchContext), @function
40 CSYM(fiber_switchContext):
42 /* Save linkage area */
70 /* We update the stack pointer here, since we do not want the GC to
71 scan the floating point registers. */
93 /* Update the old stack pointer */
96 /* Set new stack pointer */
99 /* Restore linkage area */
145 /* Set condition and link register */
149 /* Return and switch context */
152 .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
154 #elif defined(__MACH__)
156 /* Implementation for Darwin/macOS preserving callee-saved regs.
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). */
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.
166 The stack will be 16byte aligned on entry with:
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. | */
182 # define MACHINE ppc64
183 # define RED_ZONE 288
189 # define MACHINE ppc7400
190 # define RED_ZONE 220
193 # define SAVE_VECTORS 0
195 * Performs a context switch.
197 * r3 - old context pointer
198 * r4 - new context pointer
203 .globl CSYM(fiber_switchContext)
205 CSYM(fiber_switchContext):
207 /* Get the link reg. */
209 /* Get the callee-saved crs (well all of them, actually). */
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)
233 /* Save the lr and cr into the normal function linkage area. */
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)
241 /* Update the stack pointer in the old context as per comment above. */
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)
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. */
270 addi r1, r1, -(12*16+18*8)
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. */
299 addi r1, r4, -(12*16+18*8)
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. */
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)
351 /* Pick up lr and cr */
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)
381 /* Return and switch context */
385 /* Minimal CFI / FDE which does not describe the stacking of the GPRs - but only that
386 the routine has been entered/exited. */
389 # define DATA_ALIGN 0x78
390 # define ALIGN_SIZE 3
393 # define DATA_ALIGN 0x7c
394 # define ALIGN_SIZE 3
398 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
400 .set L$set$0,LECIE1-LSCIE1
401 .long L$set$0 ; Length of Common Information Entry
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
414 .p2align ALIGN_SIZE,0
417 .set L$set$1,LEFDE1-LASFDE1
418 .long L$set$1 ; FDE Length
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
428 #endif /* defined(__MACH__) */