github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/sys_windows_amd64.s (about) 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 // Offsets into Thread Environment Block (pointer in GS) 12 #define TEB_TlsSlots 0x1480 13 #define TEB_ArbitraryPtr 0x28 14 15 TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0 16 MOVQ AX, CX 17 JMP runtime·asmstdcall(SB) 18 19 // void runtime·asmstdcall(void *c); 20 TEXT runtime·asmstdcall(SB),NOSPLIT,$16 21 MOVQ SP, AX 22 ANDQ $~15, SP // alignment as per Windows requirement 23 MOVQ AX, 8(SP) 24 MOVQ CX, 0(SP) // asmcgocall will put first argument into CX. 25 26 MOVQ libcall_fn(CX), AX 27 MOVQ libcall_args(CX), SI 28 MOVQ libcall_n(CX), CX 29 30 // SetLastError(0). 31 MOVQ 0x30(GS), DI 32 MOVL $0, 0x68(DI) 33 34 SUBQ $(const_maxArgs*8), SP // room for args 35 36 // Fast version, do not store args on the stack. 37 CMPL CX, $0; JE _0args 38 CMPL CX, $1; JE _1args 39 CMPL CX, $2; JE _2args 40 CMPL CX, $3; JE _3args 41 CMPL CX, $4; JE _4args 42 43 // Check we have enough room for args. 44 CMPL CX, $const_maxArgs 45 JLE 2(PC) 46 INT $3 // not enough room -> crash 47 48 // Copy args to the stack. 49 MOVQ SP, DI 50 CLD 51 REP; MOVSQ 52 MOVQ SP, SI 53 54 // Load first 4 args into correspondent registers. 55 // Floating point arguments are passed in the XMM 56 // registers. Set them here in case any of the arguments 57 // are floating point values. For details see 58 // https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 59 _4args: 60 MOVQ 24(SI), R9 61 MOVQ R9, X3 62 _3args: 63 MOVQ 16(SI), R8 64 MOVQ R8, X2 65 _2args: 66 MOVQ 8(SI), DX 67 MOVQ DX, X1 68 _1args: 69 MOVQ 0(SI), CX 70 MOVQ CX, X0 71 _0args: 72 73 // Call stdcall function. 74 CALL AX 75 76 ADDQ $(const_maxArgs*8), SP 77 78 // Return result. 79 MOVQ 0(SP), CX 80 MOVQ 8(SP), SP 81 MOVQ AX, libcall_r1(CX) 82 // Floating point return values are returned in XMM0. Setting r2 to this 83 // value in case this call returned a floating point value. For details, 84 // see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention 85 MOVQ X0, libcall_r2(CX) 86 87 // GetLastError(). 88 MOVQ 0x30(GS), DI 89 MOVL 0x68(DI), AX 90 MOVQ AX, libcall_err(CX) 91 92 RET 93 94 // faster get/set last error 95 TEXT runtime·getlasterror(SB),NOSPLIT,$0 96 MOVQ 0x30(GS), AX 97 MOVL 0x68(AX), AX 98 MOVL AX, ret+0(FP) 99 RET 100 101 // Called by Windows as a Vectored Exception Handler (VEH). 102 // CX is pointer to struct containing 103 // exception record and context pointers. 104 // DX is the kind of sigtramp function. 105 // Return value of sigtrampgo is stored in AX. 106 TEXT sigtramp<>(SB),NOSPLIT,$0-0 107 // Switch from the host ABI to the Go ABI. 108 PUSH_REGS_HOST_TO_ABI0() 109 110 // Set up ABIInternal environment: cleared X15 and R14. 111 // R14 is cleared in case there's a non-zero value in there 112 // if called from a non-go thread. 113 XORPS X15, X15 114 XORQ R14, R14 115 116 get_tls(AX) 117 CMPQ AX, $0 118 JE 2(PC) 119 // Exception from Go thread, set R14. 120 MOVQ g(AX), R14 121 122 // Reserve space for spill slots. 123 ADJSP $16 124 MOVQ CX, AX 125 MOVQ DX, BX 126 // Calling ABIInternal because TLS might be nil. 127 CALL runtime·sigtrampgo<ABIInternal>(SB) 128 // Return value is already stored in AX. 129 130 ADJSP $-16 131 132 POP_REGS_HOST_TO_ABI0() 133 RET 134 135 // Trampoline to resume execution from exception handler. 136 // This is part of the control flow guard workaround. 137 // It switches stacks and jumps to the continuation address. 138 // R8 and R9 are set above at the end of sigtrampgo 139 // in the context that starts executing at sigresume. 140 TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0 141 MOVQ R8, SP 142 JMP R9 143 144 TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 145 // PExceptionPointers already on CX 146 MOVQ $const_callbackVEH, DX 147 JMP sigtramp<>(SB) 148 149 TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 150 // PExceptionPointers already on CX 151 MOVQ $const_callbackFirstVCH, DX 152 JMP sigtramp<>(SB) 153 154 TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 155 // PExceptionPointers already on CX 156 MOVQ $const_callbackLastVCH, DX 157 JMP sigtramp<>(SB) 158 159 TEXT runtime·sehtramp(SB),NOSPLIT,$40-0 160 // CX: PEXCEPTION_RECORD ExceptionRecord 161 // DX: ULONG64 EstablisherFrame 162 // R8: PCONTEXT ContextRecord 163 // R9: PDISPATCHER_CONTEXT DispatcherContext 164 // Switch from the host ABI to the Go ABI. 165 PUSH_REGS_HOST_TO_ABI0() 166 167 get_tls(AX) 168 CMPQ AX, $0 169 JNE 2(PC) 170 // This shouldn't happen, sehtramp is only attached to functions 171 // called from Go, and exception handlers are only called from 172 // the thread that threw the exception. 173 INT $3 174 175 // Exception from Go thread, set R14. 176 MOVQ g(AX), R14 177 178 ADJSP $40 179 MOVQ CX, 0(SP) 180 MOVQ DX, 8(SP) 181 MOVQ R8, 16(SP) 182 MOVQ R9, 24(SP) 183 CALL runtime·sehhandler(SB) 184 MOVL 32(SP), AX 185 186 ADJSP $-40 187 188 POP_REGS_HOST_TO_ABI0() 189 RET 190 191 TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 192 // Construct args vector for cgocallback(). 193 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 194 // args from the 5th on are on the stack. 195 // In any case, even if function has 0,1,2,3,4 args, there is reserved 196 // but uninitialized "shadow space" for the first 4 args. 197 // The values are in registers. 198 MOVQ CX, (16+0)(SP) 199 MOVQ DX, (16+8)(SP) 200 MOVQ R8, (16+16)(SP) 201 MOVQ R9, (16+24)(SP) 202 // R8 = address of args vector 203 LEAQ (16+0)(SP), R8 204 205 // remove return address from stack, we are not returning to callbackasm, but to its caller. 206 MOVQ 0(SP), AX 207 ADDQ $8, SP 208 209 // determine index into runtime·cbs table 210 MOVQ $runtime·callbackasm(SB), DX 211 SUBQ DX, AX 212 MOVQ $0, DX 213 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 214 DIVL CX 215 SUBQ $1, AX // subtract 1 because return PC is to the next slot 216 217 // Switch from the host ABI to the Go ABI. 218 PUSH_REGS_HOST_TO_ABI0() 219 220 // Create a struct callbackArgs on our stack to be passed as 221 // the "frame" to cgocallback and on to callbackWrap. 222 SUBQ $(24+callbackArgs__size), SP 223 MOVQ AX, (24+callbackArgs_index)(SP) // callback index 224 MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector 225 MOVQ $0, (24+callbackArgs_result)(SP) // result 226 LEAQ 24(SP), AX 227 // Call cgocallback, which will call callbackWrap(frame). 228 MOVQ $0, 16(SP) // context 229 MOVQ AX, 8(SP) // frame (address of callbackArgs) 230 LEAQ ·callbackWrap<ABIInternal>(SB), BX // cgocallback takes an ABIInternal entry-point 231 MOVQ BX, 0(SP) // PC of function value to call (callbackWrap) 232 CALL ·cgocallback(SB) 233 // Get callback result. 234 MOVQ (24+callbackArgs_result)(SP), AX 235 ADDQ $(24+callbackArgs__size), SP 236 237 POP_REGS_HOST_TO_ABI0() 238 239 // The return value was placed in AX above. 240 RET 241 242 // uint32 tstart_stdcall(M *newm); 243 TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0 244 // Switch from the host ABI to the Go ABI. 245 PUSH_REGS_HOST_TO_ABI0() 246 247 // CX contains first arg newm 248 MOVQ m_g0(CX), DX // g 249 250 // Layout new m scheduler stack on os stack. 251 MOVQ SP, AX 252 MOVQ AX, (g_stack+stack_hi)(DX) 253 SUBQ $(64*1024), AX // initial stack size (adjusted later) 254 MOVQ AX, (g_stack+stack_lo)(DX) 255 ADDQ $const_stackGuard, AX 256 MOVQ AX, g_stackguard0(DX) 257 MOVQ AX, g_stackguard1(DX) 258 259 // Set up tls. 260 LEAQ m_tls(CX), DI 261 MOVQ CX, g_m(DX) 262 MOVQ DX, g(DI) 263 CALL runtime·settls(SB) // clobbers CX 264 265 CALL runtime·stackcheck(SB) // clobbers AX,CX 266 CALL runtime·mstart(SB) 267 268 POP_REGS_HOST_TO_ABI0() 269 270 XORL AX, AX // return 0 == success 271 RET 272 273 // set tls base to DI 274 TEXT runtime·settls(SB),NOSPLIT,$0 275 MOVQ runtime·tls_g(SB), CX 276 MOVQ DI, 0(CX)(GS) 277 RET 278 279 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 280 MOVQ $_INTERRUPT_TIME, DI 281 MOVQ time_lo(DI), AX 282 IMULQ $100, AX 283 MOVQ AX, ret+0(FP) 284 RET 285 286 // func osSetupTLS(mp *m) 287 // Setup TLS. for use by needm on Windows. 288 TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8 289 MOVQ mp+0(FP), AX 290 LEAQ m_tls(AX), DI 291 CALL runtime·settls(SB) 292 RET 293 294 // This is called from rt0_go, which runs on the system stack 295 // using the initial stack allocated by the OS. 296 TEXT runtime·wintls(SB),NOSPLIT,$0 297 // Allocate a TLS slot to hold g across calls to external code 298 MOVQ SP, AX 299 ANDQ $~15, SP // alignment as per Windows requirement 300 SUBQ $48, SP // room for SP and 4 args as per Windows requirement 301 // plus one extra word to keep stack 16 bytes aligned 302 MOVQ AX, 32(SP) 303 MOVQ runtime·_TlsAlloc(SB), AX 304 CALL AX 305 MOVQ 32(SP), SP 306 307 MOVQ AX, CX // TLS index 308 309 // Assert that slot is less than 64 so we can use _TEB->TlsSlots 310 CMPQ CX, $64 311 JB ok 312 313 // Fallback to the TEB arbitrary pointer. 314 // TODO: don't use the arbitrary pointer (see go.dev/issue/59824) 315 MOVQ $TEB_ArbitraryPtr, CX 316 JMP settls 317 ok: 318 // Convert the TLS index at CX into 319 // an offset from TEB_TlsSlots. 320 SHLQ $3, CX 321 322 // Save offset from TLS into tls_g. 323 ADDQ $TEB_TlsSlots, CX 324 settls: 325 MOVQ CX, runtime·tls_g(SB) 326 RET