1/* i386 support code for fibers and multithreading.
2   Copyright (C) 2019-2022 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23<http://www.gnu.org/licenses/>.  */
24
25#include "../common/threadasm.S"
26
27/* NB: Generate the CET marker for -fcf-protection.  */
28#ifdef __CET__
29# include <cet.h>
30#endif
31
32#if !defined(__CET__)
33
34# if defined(__ELF__)
35
36#  if defined(__i386__)
37
38    .text
39    .globl CSYM(fiber_switchContext)
40    .type CSYM(fiber_switchContext), @function
41    .align 16
42CSYM(fiber_switchContext):
43    .cfi_startproc
44    // save current stack state
45    push %ebp
46    mov  %esp, %ebp
47    push %edi
48    push %esi
49    push %ebx
50    push %eax
51
52    // store oldp again with more accurate address
53    mov 8(%ebp), %eax
54    mov %esp, (%eax)
55    // load newp to begin context switch
56    mov 12(%ebp), %esp
57
58    // load saved state from new stack
59    pop %eax
60    pop %ebx
61    pop %esi
62    pop %edi
63    pop %ebp
64
65    // 'return' to complete switch
66    ret
67    .cfi_endproc
68    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
69
70#  endif /* defined(__ELF__) && defined(__i386__) */
71
72#  if defined(__x86_64__) && !defined(__ILP32__)
73
74    .text
75    .globl CSYM(fiber_switchContext)
76    .type CSYM(fiber_switchContext), @function
77    .align 16
78CSYM(fiber_switchContext):
79    .cfi_startproc
80    // Save current stack state.save current stack state
81    push %rbp
82    mov  %rsp, %rbp
83    push %rbx
84    push %r12
85    push %r13
86    push %r14
87    push %r15
88
89    // store oldp again with more accurate address
90    mov %rsp, (%rdi)
91    // load newp to begin context switch
92    mov %rsi, %rsp
93
94    // load saved state from new stack
95    pop %r15
96    pop %r14
97    pop %r13
98    pop %r12
99    pop %rbx
100    pop %rbp
101
102    // 'return' to complete switch
103    ret
104    .cfi_endproc
105   .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
106
107#  endif /* defined(__ELF__) && defined(__x86_64__) && !defined(__ILP32__) */
108
109# endif /* defined(__ELF__) */
110
111# if defined(__MACH__)
112
113#  if defined(__i386__)
114
115    .text
116    .globl CSYM(fiber_switchContext)
117    .p2align 4
118CSYM(fiber_switchContext):
119LFB0:
120    // save current stack state
121    push %ebp
122    mov  %esp, %ebp
123    push %edi
124    push %esi
125    push %ebx
126    push %eax
127
128    // store oldp again with more accurate address
129    mov 8(%ebp), %eax
130    mov %esp, (%eax)
131    // load newp to begin context switch
132    mov 12(%ebp), %esp
133
134    // load saved state from new stack
135    pop %eax
136    pop %ebx
137    pop %esi
138    pop %edi
139    pop %ebp
140
141    // 'return' to complete switch
142    ret
143LFE0:
144
145/* CFI */
146        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
147EH_frame1:
148        .set L$set$0,LECIE1-LSCIE1
149        .long L$set$0   # Length of Common Information Entry
150LSCIE1:
151        .long   0       # CIE Identifier Tag
152        .byte   0x1     # CIE Version
153        .ascii "zR\0"   # CIE Augmentation
154        .byte   0x1     # uleb128 0x1; CIE Code Alignment Factor
155        .byte   0x7c    # sleb128 -4; CIE Data Alignment Factor
156        .byte   0x8     # CIE RA Column
157        .byte   0x1     # uleb128 0x1; Augmentation size
158        .byte   0x10    # FDE Encoding (pcrel)
159        .byte   0xc     # DW_CFA_def_cfa
160        .byte   0x5     # uleb128 0x5
161        .byte   0x4     # uleb128 0x4
162        .byte   0x88    # DW_CFA_offset, column 0x8
163        .byte   0x1     # uleb128 0x1
164        .p2align 2,0
165LECIE1:
166
167/* minimal FDE - does not record the stack frame changes. */
168LSFDE1:
169        .set L$set$1,LEFDE1-LASFDE1
170        .long L$set$1   # FDE Length
171LASFDE1:
172        .long   LASFDE1-EH_frame1       # FDE CIE offset
173        .long   LFB0-.  # FDE initial location
174        .set L$set$2,LFE0-LFB0
175        .long L$set$2   # FDE address range
176        .byte   0       # uleb128 0; Augmentation size
177        .p2align 2,0
178LEFDE1:
179
180#  endif /* defined(__MACH__) && defined(__i386__) */
181
182#  if defined(__x86_64__) && !defined(__ILP32__)
183
184    .text
185    .globl CSYM(fiber_switchContext)
186    .p2align 4
187CSYM(fiber_switchContext):
188LFB0:
189    // Save current stack state.save current stack state
190    push %rbp
191    mov  %rsp, %rbp
192    push %r15
193    push %r14
194    push %r13
195    push %r12
196    push %rbx
197
198    // store oldp again with more accurate address
199    mov %rsp, (%rdi)
200    // load newp to begin context switch
201    mov %rsi, %rsp
202
203    // load saved state from new stack
204    pop %rbx
205    pop %r12
206    pop %r13
207    pop %r14
208    pop %r15
209    pop %rbp
210
211    // 'return' to complete switch
212    ret
213LFE0:
214
215/* CFI */
216        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
217EH_frame1:
218        .set L$set$0,LECIE1-LSCIE1
219        .long L$set$0   # Length of Common Information Entry
220LSCIE1:
221        .long   0       # CIE Identifier Tag
222        .byte   0x1     # CIE Version
223        .ascii "zR\0"   # CIE Augmentation
224        .byte   0x1     # uleb128 0x1; CIE Code Alignment Factor
225        .byte   0x78    # sleb128 -8; CIE Data Alignment Factor
226        .byte   0x10    # CIE RA Column
227        .byte   0x1     # uleb128 0x1; Augmentation size
228        .byte   0x10    # FDE Encoding (pcrel)
229        .byte   0xc     # DW_CFA_def_cfa
230        .byte   0x7     # uleb128 0x7
231        .byte   0x8     # uleb128 0x8
232        .byte   0x90    # DW_CFA_offset, column 0x10
233        .byte   0x1     # uleb128 0x1
234        .p2align 3,0
235LECIE1:
236
237/* minimal FDE - does not record the stack frame changes. */
238LSFDE1:
239        .set L$set$1,LEFDE1-LASFDE1
240        .long L$set$1   # FDE Length
241LASFDE1:
242        .long   LASFDE1-EH_frame1       # FDE CIE offset
243        .quad   LFB0-.  # FDE initial location
244        .set L$set$2,LFE0-LFB0
245        .quad L$set$2   # FDE address range
246        .byte   0       # uleb128 0; Augmentation size
247        .p2align 3,0
248LEFDE1:
249
250#  endif /* defined(__MACH__) && defined(__x86_64__) && !defined(__ILP32__) */
251
252# endif /* defined (__MACH__) */
253
254#endif /* !defined(__CET__) */
255