github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0 15 JMP runtime·asmstdcall(SB) 16 17 // void runtime·asmstdcall(void *c); 18 TEXT 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 40 docall: 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 58 TEXT runtime·getlasterror(SB),NOSPLIT,$0 59 MOVL 0x34(FS), AX 60 MOVL AX, ret+0(FP) 61 RET 62 63 TEXT 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. 76 TEXT 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. 106 TEXT runtime·sigresume(SB),NOSPLIT,$0 107 MOVL DX, SP 108 JMP CX 109 110 TEXT runtime·exceptiontramp(SB),NOSPLIT,$0 111 MOVL argframe+0(FP), AX 112 MOVL $const_callbackVEH, CX 113 JMP sigtramp<>(SB) 114 115 TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 116 // is never called 117 INT $3 118 119 TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 120 MOVL argframe+0(FP), AX 121 MOVL $const_callbackLastVCH, CX 122 JMP sigtramp<>(SB) 123 124 TEXT 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); 185 TEXT 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); 214 TEXT 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) 231 TEXT 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 237 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 238 loop: 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. 257 TEXT 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 273 ok: 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 280 settls: 281 MOVL CX, runtime·tls_g(SB) 282 RET