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