Text file
src/runtime/sys_windows_386.s
Documentation: runtime
1// Copyright 2009 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
10// Offsets into Thread Environment Block (pointer in FS)
11#define TEB_TlsSlots 0xE10
12#define TEB_ArbitraryPtr 0x14
13
14TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
15 JMP runtime·asmstdcall(SB)
16
17// void runtime·asmstdcall(void *c);
18TEXT runtime·asmstdcall(SB),NOSPLIT,$0
19 MOVL fn+0(FP), BX
20 MOVL SP, BP // save stack pointer
21
22 // SetLastError(0).
23 MOVL $0, 0x34(FS)
24
25 MOVL libcall_n(BX), CX
26
27 // Fast version, do not store args on the stack.
28 CMPL CX, $0
29 JE docall
30
31 // Copy args to the stack.
32 MOVL CX, AX
33 SALL $2, AX
34 SUBL AX, SP // room for args
35 MOVL SP, DI
36 MOVL libcall_args(BX), SI
37 CLD
38 REP; MOVSL
39
40docall:
41 // Call stdcall or cdecl function.
42 // DI SI BP BX are preserved, SP is not
43 CALL libcall_fn(BX)
44 MOVL BP, SP
45
46 // Return result.
47 MOVL fn+0(FP), BX
48 MOVL AX, libcall_r1(BX)
49 MOVL DX, libcall_r2(BX)
50
51 // GetLastError().
52 MOVL 0x34(FS), AX
53 MOVL AX, libcall_err(BX)
54
55 RET
56
57// faster get/set last error
58TEXT runtime·getlasterror(SB),NOSPLIT,$0
59 MOVL 0x34(FS), AX
60 MOVL AX, ret+0(FP)
61 RET
62
63TEXT runtime·sigFetchGSafe<ABIInternal>(SB),NOSPLIT,$0
64 get_tls(AX)
65 CMPL AX, $0
66 JE 2(PC)
67 MOVL g(AX), AX
68 MOVL AX, ret+0(FP)
69 RET
70
71// Called by Windows as a Vectored Exception Handler (VEH).
72// AX is pointer to struct containing
73// exception record and context pointers.
74// CX is the kind of sigtramp function.
75// Return value of sigtrampgo is stored in AX.
76TEXT sigtramp<>(SB),NOSPLIT,$0-0
77 SUBL $40, SP
78
79 // save callee-saved registers
80 MOVL BX, 28(SP)
81 MOVL BP, 16(SP)
82 MOVL SI, 20(SP)
83 MOVL DI, 24(SP)
84
85 MOVL AX, 0(SP)
86 MOVL CX, 4(SP)
87 CALL runtime·sigtrampgo(SB)
88 MOVL 8(SP), AX
89
90 // restore callee-saved registers
91 MOVL 24(SP), DI
92 MOVL 20(SP), SI
93 MOVL 16(SP), BP
94 MOVL 28(SP), BX
95
96 ADDL $40, SP
97 // RET 4 (return and pop 4 bytes parameters)
98 BYTE $0xC2; WORD $4
99 RET // unreached; make assembler happy
100
101// Trampoline to resume execution from exception handler.
102// This is part of the control flow guard workaround.
103// It switches stacks and jumps to the continuation address.
104// DX and CX are set above at the end of sigtrampgo
105// in the context that starts executing at sigresume.
106TEXT runtime·sigresume(SB),NOSPLIT,$0
107 MOVL DX, SP
108 JMP CX
109
110TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
111 MOVL argframe+0(FP), AX
112 MOVL $const_callbackVEH, CX
113 JMP sigtramp<>(SB)
114
115TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
116 // is never called
117 INT $3
118
119TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
120 MOVL argframe+0(FP), AX
121 MOVL $const_callbackLastVCH, CX
122 JMP sigtramp<>(SB)
123
124TEXT runtime·callbackasm1(SB),NOSPLIT,$0
125 MOVL 0(SP), AX // will use to find our callback context
126
127 // remove return address from stack, we are not returning to callbackasm, but to its caller.
128 ADDL $4, SP
129
130 // address to callback parameters into CX
131 LEAL 4(SP), CX
132
133 // save registers as required for windows callback
134 PUSHL DI
135 PUSHL SI
136 PUSHL BP
137 PUSHL BX
138
139 // Go ABI requires DF flag to be cleared.
140 CLD
141
142 // determine index into runtime·cbs table
143 SUBL $runtime·callbackasm(SB), AX
144 MOVL $0, DX
145 MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
146 DIVL BX
147 SUBL $1, AX // subtract 1 because return PC is to the next slot
148
149 // Create a struct callbackArgs on our stack.
150 SUBL $(12+callbackArgs__size), SP
151 MOVL AX, (12+callbackArgs_index)(SP) // callback index
152 MOVL CX, (12+callbackArgs_args)(SP) // address of args vector
153 MOVL $0, (12+callbackArgs_result)(SP) // result
154 LEAL 12(SP), AX // AX = &callbackArgs{...}
155
156 // Call cgocallback, which will call callbackWrap(frame).
157 MOVL $0, 8(SP) // context
158 MOVL AX, 4(SP) // frame (address of callbackArgs)
159 LEAL ·callbackWrap(SB), AX
160 MOVL AX, 0(SP) // PC of function to call
161 CALL runtime·cgocallback(SB)
162
163 // Get callback result.
164 MOVL (12+callbackArgs_result)(SP), AX
165 // Get popRet.
166 MOVL (12+callbackArgs_retPop)(SP), CX // Can't use a callee-save register
167 ADDL $(12+callbackArgs__size), SP
168
169 // restore registers as required for windows callback
170 POPL BX
171 POPL BP
172 POPL SI
173 POPL DI
174
175 // remove callback parameters before return (as per Windows spec)
176 POPL DX
177 ADDL CX, SP
178 PUSHL DX
179
180 CLD
181
182 RET
183
184// void tstart(M *newm);
185TEXT tstart<>(SB),NOSPLIT,$8-4
186 MOVL newm+0(FP), CX // m
187 MOVL m_g0(CX), DX // g
188
189 // Layout new m scheduler stack on os stack.
190 MOVL SP, AX
191 MOVL AX, (g_stack+stack_hi)(DX)
192 SUBL $(64*1024), AX // initial stack size (adjusted later)
193 MOVL AX, (g_stack+stack_lo)(DX)
194 ADDL $const_stackGuard, AX
195 MOVL AX, g_stackguard0(DX)
196 MOVL AX, g_stackguard1(DX)
197
198 // Set up tls.
199 LEAL m_tls(CX), DI
200 MOVL CX, g_m(DX)
201 MOVL DX, g(DI)
202 MOVL DI, 4(SP)
203 CALL runtime·setldt(SB) // clobbers CX and DX
204
205 // Someday the convention will be D is always cleared.
206 CLD
207
208 CALL runtime·stackcheck(SB) // clobbers AX,CX
209 CALL runtime·mstart(SB)
210
211 RET
212
213// uint32 tstart_stdcall(M *newm);
214TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
215 MOVL newm+0(FP), BX
216
217 PUSHL BX
218 CALL tstart<>(SB)
219 POPL BX
220
221 // Adjust stack for stdcall to return properly.
222 MOVL (SP), AX // save return address
223 ADDL $4, SP // remove single parameter
224 MOVL AX, (SP) // restore return address
225
226 XORL AX, AX // return 0 == success
227
228 RET
229
230// setldt(int slot, int base, int size)
231TEXT runtime·setldt(SB),NOSPLIT,$0-12
232 MOVL base+4(FP), DX
233 MOVL runtime·tls_g(SB), CX
234 MOVL DX, 0(CX)(FS)
235 RET
236
237TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
238loop:
239 MOVL (_INTERRUPT_TIME+time_hi1), AX
240 MOVL (_INTERRUPT_TIME+time_lo), CX
241 MOVL (_INTERRUPT_TIME+time_hi2), DI
242 CMPL AX, DI
243 JNE loop
244
245 // wintime = DI:CX, multiply by 100
246 MOVL $100, AX
247 MULL CX
248 IMULL $100, DI
249 ADDL DI, DX
250 // wintime*100 = DX:AX
251 MOVL AX, ret_lo+0(FP)
252 MOVL DX, ret_hi+4(FP)
253 RET
254
255// This is called from rt0_go, which runs on the system stack
256// using the initial stack allocated by the OS.
257TEXT runtime·wintls(SB),NOSPLIT,$0
258 // Allocate a TLS slot to hold g across calls to external code
259 MOVL SP, BP
260 MOVL runtime·_TlsAlloc(SB), AX
261 CALL AX
262 MOVL BP, SP
263
264 MOVL AX, CX // TLS index
265
266 // Assert that slot is less than 64 so we can use _TEB->TlsSlots
267 CMPL CX, $64
268 JB ok
269 // Fallback to the TEB arbitrary pointer.
270 // TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
271 MOVL $TEB_ArbitraryPtr, CX
272 JMP settls
273ok:
274 // Convert the TLS index at CX into
275 // an offset from TEB_TlsSlots.
276 SHLL $2, CX
277
278 // Save offset from TLS into tls_g.
279 ADDL $TEB_TlsSlots, CX
280settls:
281 MOVL CX, runtime·tls_g(SB)
282 RET
View as plain text