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 // void runtime·asmstdcall(void *c);
12 TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
13 // asmcgocall will put first argument into CX.
14 PUSHQ CX // save for later
15 MOVQ libcall_fn(CX), AX
16 MOVQ libcall_args(CX), SI
17 MOVQ libcall_n(CX), CX
18
19 // SetLastError(0).
20 MOVQ 0x30(GS), DI
21 MOVL $0, 0x68(DI)
22
23 SUBQ $(const_maxArgs*8), SP // room for args
24
25 // Fast version, do not store args on the stack.
26 CMPL CX, $4
27 JLE loadregs
28
29 // Check we have enough room for args.
30 CMPL CX, $const_maxArgs
31 JLE 2(PC)
32 INT $3 // not enough room -> crash
33
34 // Copy args to the stack.
35 MOVQ SP, DI
36 CLD
37 REP; MOVSQ
38 MOVQ SP, SI
39
40 loadregs:
41 // Load first 4 args into correspondent registers.
42 MOVQ 0(SI), CX
43 MOVQ 8(SI), DX
44 MOVQ 16(SI), R8
45 MOVQ 24(SI), R9
46 // Floating point arguments are passed in the XMM
47 // registers. Set them here in case any of the arguments
48 // are floating point values. For details see
49 // https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
50 MOVQ CX, X0
51 MOVQ DX, X1
52 MOVQ R8, X2
53 MOVQ R9, X3
54
55 // Call stdcall function.
56 CALL AX
57
58 ADDQ $(const_maxArgs*8), SP
59
60 // Return result.
61 POPQ CX
62 MOVQ AX, libcall_r1(CX)
63 // Floating point return values are returned in XMM0. Setting r2 to this
64 // value in case this call returned a floating point value. For details,
65 // see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
66 MOVQ X0, libcall_r2(CX)
67
68 // GetLastError().
69 MOVQ 0x30(GS), DI
70 MOVL 0x68(DI), AX
71 MOVQ AX, libcall_err(CX)
72
73 RET
74
75 TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48
76 // stderr
77 MOVQ $-12, CX // stderr
78 MOVQ CX, 0(SP)
79 MOVQ runtime·_GetStdHandle(SB), AX
80 CALL AX
81
82 MOVQ AX, CX // handle
83 MOVQ CX, 0(SP)
84 MOVQ $runtime·badsignalmsg(SB), DX // pointer
85 MOVQ DX, 8(SP)
86 MOVL $runtime·badsignallen(SB), R8 // count
87 MOVQ R8, 16(SP)
88 LEAQ 40(SP), R9 // written count
89 MOVQ $0, 0(R9)
90 MOVQ R9, 24(SP)
91 MOVQ $0, 32(SP) // overlapped
92 MOVQ runtime·_WriteFile(SB), AX
93 CALL AX
94
95 // Does not return.
96 CALL runtime·abort(SB)
97 RET
98
99 // faster get/set last error
100 TEXT runtime·getlasterror(SB),NOSPLIT,$0
101 MOVQ 0x30(GS), AX
102 MOVL 0x68(AX), AX
103 MOVL AX, ret+0(FP)
104 RET
105
106 // Called by Windows as a Vectored Exception Handler (VEH).
107 // First argument is pointer to struct containing
108 // exception record and context pointers.
109 // Handler function is stored in AX.
110 // Return 0 for 'not handled', -1 for handled.
111 TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
112 // CX: PEXCEPTION_POINTERS ExceptionInfo
113
114 // Switch from the host ABI to the Go ABI.
115 PUSH_REGS_HOST_TO_ABI0()
116 // Make stack space for the rest of the function.
117 ADJSP $48
118
119 MOVQ AX, R15 // save handler address
120
121 // find g
122 get_tls(DX)
123 CMPQ DX, $0
124 JNE 3(PC)
125 MOVQ $0, AX // continue
126 JMP done
127 MOVQ g(DX), DX
128 CMPQ DX, $0
129 JNE 2(PC)
130 CALL runtime·badsignal2(SB)
131
132 // save g and SP in case of stack switch
133 MOVQ DX, 32(SP) // g
134 MOVQ SP, 40(SP)
135
136 // do we need to switch to the g0 stack?
137 MOVQ g_m(DX), BX
138 MOVQ m_g0(BX), BX
139 CMPQ DX, BX
140 JEQ g0
141
142 // switch to g0 stack
143 get_tls(BP)
144 MOVQ BX, g(BP)
145 MOVQ (g_sched+gobuf_sp)(BX), DI
146 // make room for sighandler arguments
147 // and re-save old SP for restoring later.
148 // Adjust g0 stack by the space we're using and
149 // save SP at the same place on the g0 stack.
150 // The 40(DI) here must match the 40(SP) above.
151 SUBQ $(REGS_HOST_TO_ABI0_STACK + 48), DI
152 MOVQ SP, 40(DI)
153 MOVQ DI, SP
154
155 g0:
156 MOVQ 0(CX), BX // ExceptionRecord*
157 MOVQ 8(CX), CX // Context*
158 MOVQ BX, 0(SP)
159 MOVQ CX, 8(SP)
160 MOVQ DX, 16(SP)
161 CALL R15 // call handler
162 // AX is set to report result back to Windows
163 MOVL 24(SP), AX
164
165 // switch back to original stack and g
166 // no-op if we never left.
167 MOVQ 40(SP), SP
168 MOVQ 32(SP), DX
169 get_tls(BP)
170 MOVQ DX, g(BP)
171
172 done:
173 ADJSP $-48
174 POP_REGS_HOST_TO_ABI0()
175
176 RET
177
178 TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
179 MOVQ $runtime·exceptionhandler(SB), AX
180 JMP sigtramp<>(SB)
181
182 TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
183 MOVQ $runtime·firstcontinuehandler(SB), AX
184 JMP sigtramp<>(SB)
185
186 TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
187 MOVQ $runtime·lastcontinuehandler(SB), AX
188 JMP sigtramp<>(SB)
189
190 GLOBL runtime·cbctxts(SB), NOPTR, $8
191
192 TEXT runtime·callbackasm1(SB),NOSPLIT,$0
193 // Construct args vector for cgocallback().
194 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
195 // args from the 5th on are on the stack.
196 // In any case, even if function has 0,1,2,3,4 args, there is reserved
197 // but uninitialized "shadow space" for the first 4 args.
198 // The values are in registers.
199 MOVQ CX, (16+0)(SP)
200 MOVQ DX, (16+8)(SP)
201 MOVQ R8, (16+16)(SP)
202 MOVQ R9, (16+24)(SP)
203 // R8 = address of args vector
204 LEAQ (16+0)(SP), R8
205
206 // remove return address from stack, we are not returning to callbackasm, but to its caller.
207 MOVQ 0(SP), AX
208 ADDQ $8, SP
209
210 // determine index into runtime·cbs table
211 MOVQ $runtime·callbackasm(SB), DX
212 SUBQ DX, AX
213 MOVQ $0, DX
214 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
215 DIVL CX
216 SUBQ $1, AX // subtract 1 because return PC is to the next slot
217
218 // Switch from the host ABI to the Go ABI.
219 PUSH_REGS_HOST_TO_ABI0()
220
221 // Create a struct callbackArgs on our stack to be passed as
222 // the "frame" to cgocallback and on to callbackWrap.
223 SUBQ $(24+callbackArgs__size), SP
224 MOVQ AX, (24+callbackArgs_index)(SP) // callback index
225 MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
226 MOVQ $0, (24+callbackArgs_result)(SP) // result
227 LEAQ 24(SP), AX
228 // Call cgocallback, which will call callbackWrap(frame).
229 MOVQ $0, 16(SP) // context
230 MOVQ AX, 8(SP) // frame (address of callbackArgs)
231 LEAQ ·callbackWrap<ABIInternal>(SB), BX // cgocallback takes an ABIInternal entry-point
232 MOVQ BX, 0(SP) // PC of function value to call (callbackWrap)
233 CALL ·cgocallback(SB)
234 // Get callback result.
235 MOVQ (24+callbackArgs_result)(SP), AX
236 ADDQ $(24+callbackArgs__size), SP
237
238 POP_REGS_HOST_TO_ABI0()
239
240 // The return value was placed in AX above.
241 RET
242
243 // uint32 tstart_stdcall(M *newm);
244 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
245 // Switch from the host ABI to the Go ABI.
246 PUSH_REGS_HOST_TO_ABI0()
247
248 // CX contains first arg newm
249 MOVQ m_g0(CX), DX // g
250
251 // Layout new m scheduler stack on os stack.
252 MOVQ SP, AX
253 MOVQ AX, (g_stack+stack_hi)(DX)
254 SUBQ $(64*1024), AX // initial stack size (adjusted later)
255 MOVQ AX, (g_stack+stack_lo)(DX)
256 ADDQ $const__StackGuard, AX
257 MOVQ AX, g_stackguard0(DX)
258 MOVQ AX, g_stackguard1(DX)
259
260 // Set up tls.
261 LEAQ m_tls(CX), SI
262 MOVQ SI, 0x28(GS)
263 MOVQ CX, g_m(DX)
264 MOVQ DX, g(SI)
265
266 CALL runtime·stackcheck(SB) // clobbers AX,CX
267 CALL runtime·mstart(SB)
268
269 POP_REGS_HOST_TO_ABI0()
270
271 XORL AX, AX // return 0 == success
272 RET
273
274 // set tls base to DI
275 TEXT runtime·settls(SB),NOSPLIT,$0
276 MOVQ DI, 0x28(GS)
277 RET
278
279 // Runs on OS stack.
280 // duration (in -100ns units) is in dt+0(FP).
281 // g may be nil.
282 // The function leaves room for 4 syscall parameters
283 // (as per windows amd64 calling convention).
284 TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48-4
285 MOVLQSX dt+0(FP), BX
286 MOVQ SP, AX
287 ANDQ $~15, SP // alignment as per Windows requirement
288 MOVQ AX, 40(SP)
289 LEAQ 32(SP), R8 // ptime
290 MOVQ BX, (R8)
291 MOVQ $-1, CX // handle
292 MOVQ $0, DX // alertable
293 MOVQ runtime·_NtWaitForSingleObject(SB), AX
294 CALL AX
295 MOVQ 40(SP), SP
296 RET
297
298 // Runs on OS stack. duration (in -100ns units) is in dt+0(FP).
299 // g is valid.
300 TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72-4
301 MOVLQSX dt+0(FP), BX
302 get_tls(CX)
303
304 MOVQ SP, AX
305 ANDQ $~15, SP // alignment as per Windows requirement
306 MOVQ AX, 64(SP)
307
308 MOVQ g(CX), CX
309 MOVQ g_m(CX), CX
310 MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer
311 MOVQ CX, 48(SP) // save hTimer for later
312 LEAQ 56(SP), DX // lpDueTime
313 MOVQ BX, (DX)
314 MOVQ $0, R8 // lPeriod
315 MOVQ $0, R9 // pfnCompletionRoutine
316 MOVQ $0, AX
317 MOVQ AX, 32(SP) // lpArgToCompletionRoutine
318 MOVQ AX, 40(SP) // fResume
319 MOVQ runtime·_SetWaitableTimer(SB), AX
320 CALL AX
321
322 MOVQ 48(SP), CX // handle
323 MOVQ $0, DX // alertable
324 MOVQ $0, R8 // ptime
325 MOVQ runtime·_NtWaitForSingleObject(SB), AX
326 CALL AX
327
328 MOVQ 64(SP), SP
329 RET
330
331 // Runs on OS stack.
332 TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
333 MOVQ SP, AX
334 ANDQ $~15, SP // alignment as per Windows requirement
335 SUBQ $(48), SP // room for SP and 4 args as per Windows requirement
336 // plus one extra word to keep stack 16 bytes aligned
337 MOVQ AX, 32(SP)
338 MOVQ runtime·_SwitchToThread(SB), AX
339 CALL AX
340 MOVQ 32(SP), SP
341 RET
342
343 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
344 CMPB runtime·useQPCTime(SB), $0
345 JNE useQPC
346 MOVQ $_INTERRUPT_TIME, DI
347 MOVQ time_lo(DI), AX
348 IMULQ $100, AX
349 MOVQ AX, ret+0(FP)
350 RET
351 useQPC:
352 JMP runtime·nanotimeQPC(SB)
353 RET
354
355 // func osSetupTLS(mp *m)
356 // Setup TLS. for use by needm on Windows.
357 TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
358 MOVQ mp+0(FP), AX
359 LEAQ m_tls(AX), DI
360 CALL runtime·settls(SB)
361 RET
362
View as plain text