]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/sys_windows_amd64.s
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / runtime / sys_windows_amd64.s
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "go_asm.h"
6 #include "go_tls.h"
7 #include "textflag.h"
8 #include "time_windows.h"
9 #include "cgo/abi_amd64.h"
10
11 // Offsets into Thread Environment Block (pointer in GS)
12 #define TEB_TlsSlots 0x1480
13 #define TEB_ArbitraryPtr 0x28
14
15 TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
16         MOVQ    AX, CX
17         JMP     runtime·asmstdcall(SB)
18
19 // void runtime·asmstdcall(void *c);
20 TEXT runtime·asmstdcall(SB),NOSPLIT,$16
21         MOVQ    SP, AX
22         ANDQ    $~15, SP        // alignment as per Windows requirement
23         MOVQ    AX, 8(SP)
24         MOVQ    CX, 0(SP)       // asmcgocall will put first argument into CX.
25
26         MOVQ    libcall_fn(CX), AX
27         MOVQ    libcall_args(CX), SI
28         MOVQ    libcall_n(CX), CX
29
30         // SetLastError(0).
31         MOVQ    0x30(GS), DI
32         MOVL    $0, 0x68(DI)
33
34         SUBQ    $(const_maxArgs*8), SP  // room for args
35
36         // Fast version, do not store args on the stack nor
37         // load them into registers.
38         CMPL    CX, $0
39         JE      docall
40
41         // Fast version, do not store args on the stack.
42         CMPL    CX, $4
43         JLE     loadregs
44
45         // Check we have enough room for args.
46         CMPL    CX, $const_maxArgs
47         JLE     2(PC)
48         INT     $3                      // not enough room -> crash
49
50         // Copy args to the stack.
51         MOVQ    SP, DI
52         CLD
53         REP; MOVSQ
54         MOVQ    SP, SI
55
56 loadregs:
57         // Load first 4 args into correspondent registers.
58         MOVQ    0(SI), CX
59         MOVQ    8(SI), DX
60         MOVQ    16(SI), R8
61         MOVQ    24(SI), R9
62         // Floating point arguments are passed in the XMM
63         // registers. Set them here in case any of the arguments
64         // are floating point values. For details see
65         //      https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
66         MOVQ    CX, X0
67         MOVQ    DX, X1
68         MOVQ    R8, X2
69         MOVQ    R9, X3
70
71 docall:
72         // Call stdcall function.
73         CALL    AX
74
75         ADDQ    $(const_maxArgs*8), SP
76
77         // Return result.
78         MOVQ    0(SP), CX
79         MOVQ    8(SP), SP
80         MOVQ    AX, libcall_r1(CX)
81         // Floating point return values are returned in XMM0. Setting r2 to this
82         // value in case this call returned a floating point value. For details,
83         // see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
84         MOVQ    X0, libcall_r2(CX)
85
86         // GetLastError().
87         MOVQ    0x30(GS), DI
88         MOVL    0x68(DI), AX
89         MOVQ    AX, libcall_err(CX)
90
91         RET
92
93 // faster get/set last error
94 TEXT runtime·getlasterror(SB),NOSPLIT,$0
95         MOVQ    0x30(GS), AX
96         MOVL    0x68(AX), AX
97         MOVL    AX, ret+0(FP)
98         RET
99
100 // Called by Windows as a Vectored Exception Handler (VEH).
101 // CX is pointer to struct containing
102 // exception record and context pointers.
103 // DX is the kind of sigtramp function.
104 // Return value of sigtrampgo is stored in AX.
105 TEXT sigtramp<>(SB),NOSPLIT,$0-0
106         // Switch from the host ABI to the Go ABI.
107         PUSH_REGS_HOST_TO_ABI0()
108
109         // Set up ABIInternal environment: cleared X15 and R14.
110         // R14 is cleared in case there's a non-zero value in there
111         // if called from a non-go thread.
112         XORPS   X15, X15
113         XORQ    R14, R14
114
115         get_tls(AX)
116         CMPQ    AX, $0
117         JE      2(PC)
118         // Exception from Go thread, set R14.
119         MOVQ    g(AX), R14
120
121         // Reserve space for spill slots.
122         ADJSP   $16
123         MOVQ    CX, AX
124         MOVQ    DX, BX
125         // Calling ABIInternal because TLS might be nil.
126         CALL    runtime·sigtrampgo<ABIInternal>(SB)
127         // Return value is already stored in AX.
128
129         ADJSP   $-16
130
131         POP_REGS_HOST_TO_ABI0()
132         RET
133
134 // Trampoline to resume execution from exception handler.
135 // This is part of the control flow guard workaround.
136 // It switches stacks and jumps to the continuation address.
137 // R8 and R9 are set above at the end of sigtrampgo
138 // in the context that starts executing at sigresume.
139 TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
140         MOVQ    R8, SP
141         JMP     R9
142
143 TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
144         // PExceptionPointers already on CX
145         MOVQ    $const_callbackVEH, DX
146         JMP     sigtramp<>(SB)
147
148 TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
149         // PExceptionPointers already on CX
150         MOVQ    $const_callbackFirstVCH, DX
151         JMP     sigtramp<>(SB)
152
153 TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
154         // PExceptionPointers already on CX
155         MOVQ    $const_callbackLastVCH, DX
156         JMP     sigtramp<>(SB)
157
158 TEXT runtime·sehtramp(SB),NOSPLIT,$40-0
159         // CX: PEXCEPTION_RECORD ExceptionRecord
160         // DX: ULONG64 EstablisherFrame
161         // R8: PCONTEXT ContextRecord
162         // R9: PDISPATCHER_CONTEXT DispatcherContext
163         // Switch from the host ABI to the Go ABI.
164         PUSH_REGS_HOST_TO_ABI0()
165
166         get_tls(AX)
167         CMPQ    AX, $0
168         JNE     2(PC)
169         // This shouldn't happen, sehtramp is only attached to functions
170         // called from Go, and exception handlers are only called from
171         // the thread that threw the exception.
172         INT     $3
173
174         // Exception from Go thread, set R14.
175         MOVQ    g(AX), R14
176
177         ADJSP   $40
178         MOVQ    CX, 0(SP)
179         MOVQ    DX, 8(SP)
180         MOVQ    R8, 16(SP)
181         MOVQ    R9, 24(SP)
182         CALL    runtime·sehhandler(SB)
183         MOVL    32(SP), AX
184
185         ADJSP   $-40
186
187         POP_REGS_HOST_TO_ABI0()
188         RET
189
190 TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
191         // Construct args vector for cgocallback().
192         // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
193         // args from the 5th on are on the stack.
194         // In any case, even if function has 0,1,2,3,4 args, there is reserved
195         // but uninitialized "shadow space" for the first 4 args.
196         // The values are in registers.
197         MOVQ    CX, (16+0)(SP)
198         MOVQ    DX, (16+8)(SP)
199         MOVQ    R8, (16+16)(SP)
200         MOVQ    R9, (16+24)(SP)
201         // R8 = address of args vector
202         LEAQ    (16+0)(SP), R8
203
204         // remove return address from stack, we are not returning to callbackasm, but to its caller.
205         MOVQ    0(SP), AX
206         ADDQ    $8, SP
207
208         // determine index into runtime·cbs table
209         MOVQ    $runtime·callbackasm(SB), DX
210         SUBQ    DX, AX
211         MOVQ    $0, DX
212         MOVQ    $5, CX  // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
213         DIVL    CX
214         SUBQ    $1, AX  // subtract 1 because return PC is to the next slot
215
216         // Switch from the host ABI to the Go ABI.
217         PUSH_REGS_HOST_TO_ABI0()
218
219         // Create a struct callbackArgs on our stack to be passed as
220         // the "frame" to cgocallback and on to callbackWrap.
221         SUBQ    $(24+callbackArgs__size), SP
222         MOVQ    AX, (24+callbackArgs_index)(SP)         // callback index
223         MOVQ    R8, (24+callbackArgs_args)(SP)          // address of args vector
224         MOVQ    $0, (24+callbackArgs_result)(SP)        // result
225         LEAQ    24(SP), AX
226         // Call cgocallback, which will call callbackWrap(frame).
227         MOVQ    $0, 16(SP)      // context
228         MOVQ    AX, 8(SP)       // frame (address of callbackArgs)
229         LEAQ    ·callbackWrap<ABIInternal>(SB), BX     // cgocallback takes an ABIInternal entry-point
230         MOVQ    BX, 0(SP)       // PC of function value to call (callbackWrap)
231         CALL    ·cgocallback(SB)
232         // Get callback result.
233         MOVQ    (24+callbackArgs_result)(SP), AX
234         ADDQ    $(24+callbackArgs__size), SP
235
236         POP_REGS_HOST_TO_ABI0()
237
238         // The return value was placed in AX above.
239         RET
240
241 // uint32 tstart_stdcall(M *newm);
242 TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
243         // Switch from the host ABI to the Go ABI.
244         PUSH_REGS_HOST_TO_ABI0()
245
246         // CX contains first arg newm
247         MOVQ    m_g0(CX), DX            // g
248
249         // Layout new m scheduler stack on os stack.
250         MOVQ    SP, AX
251         MOVQ    AX, (g_stack+stack_hi)(DX)
252         SUBQ    $(64*1024), AX          // initial stack size (adjusted later)
253         MOVQ    AX, (g_stack+stack_lo)(DX)
254         ADDQ    $const_stackGuard, AX
255         MOVQ    AX, g_stackguard0(DX)
256         MOVQ    AX, g_stackguard1(DX)
257
258         // Set up tls.
259         LEAQ    m_tls(CX), DI
260         MOVQ    CX, g_m(DX)
261         MOVQ    DX, g(DI)
262         CALL    runtime·settls(SB) // clobbers CX
263
264         CALL    runtime·stackcheck(SB) // clobbers AX,CX
265         CALL    runtime·mstart(SB)
266
267         POP_REGS_HOST_TO_ABI0()
268
269         XORL    AX, AX                  // return 0 == success
270         RET
271
272 // set tls base to DI
273 TEXT runtime·settls(SB),NOSPLIT,$0
274         MOVQ    runtime·tls_g(SB), CX
275         MOVQ    DI, 0(CX)(GS)
276         RET
277
278 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
279         MOVQ    $_INTERRUPT_TIME, DI
280         MOVQ    time_lo(DI), AX
281         IMULQ   $100, AX
282         MOVQ    AX, ret+0(FP)
283         RET
284
285 // func osSetupTLS(mp *m)
286 // Setup TLS. for use by needm on Windows.
287 TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
288         MOVQ    mp+0(FP), AX
289         LEAQ    m_tls(AX), DI
290         CALL    runtime·settls(SB)
291         RET
292
293 // This is called from rt0_go, which runs on the system stack
294 // using the initial stack allocated by the OS.
295 TEXT runtime·wintls(SB),NOSPLIT,$0
296         // Allocate a TLS slot to hold g across calls to external code
297         MOVQ    SP, AX
298         ANDQ    $~15, SP        // alignment as per Windows requirement
299         SUBQ    $48, SP // room for SP and 4 args as per Windows requirement
300                         // plus one extra word to keep stack 16 bytes aligned
301         MOVQ    AX, 32(SP)
302         MOVQ    runtime·_TlsAlloc(SB), AX
303         CALL    AX
304         MOVQ    32(SP), SP
305
306         MOVQ    AX, CX  // TLS index
307
308         // Assert that slot is less than 64 so we can use _TEB->TlsSlots
309         CMPQ    CX, $64
310         JB      ok
311
312         // Fallback to the TEB arbitrary pointer.
313         // TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
314         MOVQ    $TEB_ArbitraryPtr, CX
315         JMP     settls
316 ok:
317         // Convert the TLS index at CX into
318         // an offset from TEB_TlsSlots.
319         SHLQ    $3, CX
320
321         // Save offset from TLS into tls_g.
322         ADDQ    $TEB_TlsSlots, CX
323 settls:
324         MOVQ    CX, runtime·tls_g(SB)
325         RET