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