Text file
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 // faster get/set last error
16 TEXT runtime·getlasterror(SB),NOSPLIT,$0
17 MOVQ 0x30(GS), AX
18 MOVL 0x68(AX), AX
19 MOVL AX, ret+0(FP)
20 RET
21
22 // Called by Windows as a Vectored Exception Handler (VEH).
23 // CX is pointer to struct containing
24 // exception record and context pointers.
25 // DX is the kind of sigtramp function.
26 // Return value of sigtrampgo is stored in AX.
27 TEXT sigtramp<>(SB),NOSPLIT,$0-0
28 // Switch from the host ABI to the Go ABI.
29 PUSH_REGS_HOST_TO_ABI0()
30
31 // Set up ABIInternal environment: cleared X15 and R14.
32 // R14 is cleared in case there's a non-zero value in there
33 // if called from a non-go thread.
34 XORPS X15, X15
35 XORQ R14, R14
36
37 get_tls(AX)
38 CMPQ AX, $0
39 JE 2(PC)
40 // Exception from Go thread, set R14.
41 MOVQ g(AX), R14
42
43 // Reserve space for spill slots.
44 ADJSP $16
45 MOVQ CX, AX
46 MOVQ DX, BX
47 // Calling ABIInternal because TLS might be nil.
48 CALL runtime·sigtrampgo<ABIInternal>(SB)
49 // Return value is already stored in AX.
50
51 ADJSP $-16
52
53 POP_REGS_HOST_TO_ABI0()
54 RET
55
56 // Trampoline to resume execution from exception handler.
57 // This is part of the control flow guard workaround.
58 // It switches stacks and jumps to the continuation address.
59 // R8 and R9 are set above at the end of sigtrampgo
60 // in the context that starts executing at sigresume.
61 TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
62 MOVQ R8, SP
63 JMP R9
64
65 TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
66 // PExceptionPointers already on CX
67 MOVQ $const_callbackVEH, DX
68 JMP sigtramp<>(SB)
69
70 TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
71 // PExceptionPointers already on CX
72 MOVQ $const_callbackFirstVCH, DX
73 JMP sigtramp<>(SB)
74
75 TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
76 // PExceptionPointers already on CX
77 MOVQ $const_callbackLastVCH, DX
78 JMP sigtramp<>(SB)
79
80 TEXT runtime·sehtramp(SB),NOSPLIT,$40-0
81 // CX: PEXCEPTION_RECORD ExceptionRecord
82 // DX: ULONG64 EstablisherFrame
83 // R8: PCONTEXT ContextRecord
84 // R9: PDISPATCHER_CONTEXT DispatcherContext
85 // Switch from the host ABI to the Go ABI.
86 PUSH_REGS_HOST_TO_ABI0()
87
88 get_tls(AX)
89 CMPQ AX, $0
90 JNE 2(PC)
91 // This shouldn't happen, sehtramp is only attached to functions
92 // called from Go, and exception handlers are only called from
93 // the thread that threw the exception.
94 INT $3
95
96 // Exception from Go thread, set R14.
97 MOVQ g(AX), R14
98
99 ADJSP $40
100 MOVQ CX, 0(SP)
101 MOVQ DX, 8(SP)
102 MOVQ R8, 16(SP)
103 MOVQ R9, 24(SP)
104 CALL runtime·sehhandler(SB)
105 MOVL 32(SP), AX
106
107 ADJSP $-40
108
109 POP_REGS_HOST_TO_ABI0()
110 RET
111
112 TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
113 // Construct args vector for cgocallback().
114 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
115 // args from the 5th on are on the stack.
116 // In any case, even if function has 0,1,2,3,4 args, there is reserved
117 // but uninitialized "shadow space" for the first 4 args.
118 // The values are in registers.
119 MOVQ CX, (16+0)(SP)
120 MOVQ DX, (16+8)(SP)
121 MOVQ R8, (16+16)(SP)
122 MOVQ R9, (16+24)(SP)
123 // R8 = address of args vector
124 LEAQ (16+0)(SP), R8
125
126 // remove return address from stack, we are not returning to callbackasm, but to its caller.
127 MOVQ 0(SP), AX
128 ADDQ $8, SP
129
130 // determine index into runtime·cbs table
131 MOVQ $runtime·callbackasm(SB), DX
132 SUBQ DX, AX
133 MOVQ $0, DX
134 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
135 DIVL CX
136 SUBQ $1, AX // subtract 1 because return PC is to the next slot
137
138 // Switch from the host ABI to the Go ABI.
139 PUSH_REGS_HOST_TO_ABI0()
140
141 // Create a struct callbackArgs on our stack to be passed as
142 // the "frame" to cgocallback and on to callbackWrap.
143 SUBQ $(24+callbackArgs__size), SP
144 MOVQ AX, (24+callbackArgs_index)(SP) // callback index
145 MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
146 MOVQ $0, (24+callbackArgs_result)(SP) // result
147 LEAQ 24(SP), AX
148 // Call cgocallback, which will call callbackWrap(frame).
149 MOVQ $0, 16(SP) // context
150 MOVQ AX, 8(SP) // frame (address of callbackArgs)
151 LEAQ ·callbackWrap<ABIInternal>(SB), BX // cgocallback takes an ABIInternal entry-point
152 MOVQ BX, 0(SP) // PC of function value to call (callbackWrap)
153 CALL ·cgocallback(SB)
154 // Get callback result.
155 MOVQ (24+callbackArgs_result)(SP), AX
156 ADDQ $(24+callbackArgs__size), SP
157
158 POP_REGS_HOST_TO_ABI0()
159
160 // The return value was placed in AX above.
161 RET
162
163 // uint32 tstart_stdcall(M *newm);
164 TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
165 // Switch from the host ABI to the Go ABI.
166 PUSH_REGS_HOST_TO_ABI0()
167
168 // CX contains first arg newm
169 MOVQ m_g0(CX), DX // g
170
171 // Layout new m scheduler stack on os stack.
172 MOVQ SP, AX
173 MOVQ AX, (g_stack+stack_hi)(DX)
174 SUBQ $(64*1024), AX // initial stack size (adjusted later)
175 MOVQ AX, (g_stack+stack_lo)(DX)
176 ADDQ $const_stackGuard, AX
177 MOVQ AX, g_stackguard0(DX)
178 MOVQ AX, g_stackguard1(DX)
179
180 // Set up tls.
181 LEAQ m_tls(CX), DI
182 MOVQ CX, g_m(DX)
183 MOVQ DX, g(DI)
184 CALL runtime·settls(SB) // clobbers CX
185
186 CALL runtime·stackcheck(SB) // clobbers AX,CX
187 CALL runtime·mstart(SB)
188
189 POP_REGS_HOST_TO_ABI0()
190
191 XORL AX, AX // return 0 == success
192 RET
193
194 // set tls base to DI
195 TEXT runtime·settls(SB),NOSPLIT,$0
196 MOVQ runtime·tls_g(SB), CX
197 MOVQ DI, 0(CX)(GS)
198 RET
199
200 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
201 MOVQ $_INTERRUPT_TIME, DI
202 MOVQ time_lo(DI), AX
203 IMULQ $100, AX
204 MOVQ AX, ret+0(FP)
205 RET
206
207 // func osSetupTLS(mp *m)
208 // Setup TLS. for use by needm on Windows.
209 TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
210 MOVQ mp+0(FP), AX
211 LEAQ m_tls(AX), DI
212 CALL runtime·settls(SB)
213 RET
214
215 // This is called from rt0_go, which runs on the system stack
216 // using the initial stack allocated by the OS.
217 TEXT runtime·wintls(SB),NOSPLIT,$0
218 // Allocate a TLS slot to hold g across calls to external code
219 MOVQ SP, AX
220 ANDQ $~15, SP // alignment as per Windows requirement
221 SUBQ $48, SP // room for SP and 4 args as per Windows requirement
222 // plus one extra word to keep stack 16 bytes aligned
223 MOVQ AX, 32(SP)
224 MOVQ runtime·_TlsAlloc(SB), AX
225 CALL AX
226 MOVQ 32(SP), SP
227
228 MOVQ AX, CX // TLS index
229
230 // Assert that slot is less than 64 so we can use _TEB->TlsSlots
231 CMPQ CX, $64
232 JB ok
233
234 // Fallback to the TEB arbitrary pointer.
235 // TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
236 MOVQ $TEB_ArbitraryPtr, CX
237 JMP settls
238 ok:
239 // Convert the TLS index at CX into
240 // an offset from TEB_TlsSlots.
241 SHLQ $3, CX
242
243 // Save offset from TLS into tls_g.
244 ADDQ $TEB_TlsSlots, CX
245 settls:
246 MOVQ CX, runtime·tls_g(SB)
247 RET
248
View as plain text