github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/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 // void runtime·asmstdcall(void *c); 12 TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 13 // asmcgocall will put first argument into CX. 14 PUSHQ CX // save for later 15 MOVQ libcall_fn(CX), AX 16 MOVQ libcall_args(CX), SI 17 MOVQ libcall_n(CX), CX 18 19 // SetLastError(0). 20 MOVQ 0x30(GS), DI 21 MOVL $0, 0x68(DI) 22 23 SUBQ $(const_maxArgs*8), SP // room for args 24 25 // Fast version, do not store args on the stack. 26 CMPL CX, $4 27 JLE loadregs 28 29 // Check we have enough room for args. 30 CMPL CX, $const_maxArgs 31 JLE 2(PC) 32 INT $3 // not enough room -> crash 33 34 // Copy args to the stack. 35 MOVQ SP, DI 36 CLD 37 REP; MOVSQ 38 MOVQ SP, SI 39 40 loadregs: 41 // Load first 4 args into correspondent registers. 42 MOVQ 0(SI), CX 43 MOVQ 8(SI), DX 44 MOVQ 16(SI), R8 45 MOVQ 24(SI), R9 46 // Floating point arguments are passed in the XMM 47 // registers. Set them here in case any of the arguments 48 // are floating point values. For details see 49 // https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx 50 MOVQ CX, X0 51 MOVQ DX, X1 52 MOVQ R8, X2 53 MOVQ R9, X3 54 55 // Call stdcall function. 56 CALL AX 57 58 ADDQ $(const_maxArgs*8), SP 59 60 // Return result. 61 POPQ CX 62 MOVQ AX, libcall_r1(CX) 63 // Floating point return values are returned in XMM0. Setting r2 to this 64 // value in case this call returned a floating point value. For details, 65 // see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention 66 MOVQ X0, libcall_r2(CX) 67 68 // GetLastError(). 69 MOVQ 0x30(GS), DI 70 MOVL 0x68(DI), AX 71 MOVQ AX, libcall_err(CX) 72 73 RET 74 75 TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48 76 // stderr 77 MOVQ $-12, CX // stderr 78 MOVQ CX, 0(SP) 79 MOVQ runtime·_GetStdHandle(SB), AX 80 CALL AX 81 82 MOVQ AX, CX // handle 83 MOVQ CX, 0(SP) 84 MOVQ $runtime·badsignalmsg(SB), DX // pointer 85 MOVQ DX, 8(SP) 86 MOVL $runtime·badsignallen(SB), R8 // count 87 MOVQ R8, 16(SP) 88 LEAQ 40(SP), R9 // written count 89 MOVQ $0, 0(R9) 90 MOVQ R9, 24(SP) 91 MOVQ $0, 32(SP) // overlapped 92 MOVQ runtime·_WriteFile(SB), AX 93 CALL AX 94 95 // Does not return. 96 CALL runtime·abort(SB) 97 RET 98 99 // faster get/set last error 100 TEXT runtime·getlasterror(SB),NOSPLIT,$0 101 MOVQ 0x30(GS), AX 102 MOVL 0x68(AX), AX 103 MOVL AX, ret+0(FP) 104 RET 105 106 // Called by Windows as a Vectored Exception Handler (VEH). 107 // First argument is pointer to struct containing 108 // exception record and context pointers. 109 // Handler function is stored in AX. 110 // Return 0 for 'not handled', -1 for handled. 111 TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0 112 // CX: PEXCEPTION_POINTERS ExceptionInfo 113 114 // Switch from the host ABI to the Go ABI. 115 PUSH_REGS_HOST_TO_ABI0() 116 // Make stack space for the rest of the function. 117 ADJSP $48 118 119 MOVQ AX, R15 // save handler address 120 121 // find g 122 get_tls(DX) 123 CMPQ DX, $0 124 JNE 3(PC) 125 MOVQ $0, AX // continue 126 JMP done 127 MOVQ g(DX), DX 128 CMPQ DX, $0 129 JNE 2(PC) 130 CALL runtime·badsignal2(SB) 131 132 // save g and SP in case of stack switch 133 MOVQ DX, 32(SP) // g 134 MOVQ SP, 40(SP) 135 136 // do we need to switch to the g0 stack? 137 MOVQ g_m(DX), BX 138 MOVQ m_g0(BX), BX 139 CMPQ DX, BX 140 JEQ g0 141 142 // switch to g0 stack 143 get_tls(BP) 144 MOVQ BX, g(BP) 145 MOVQ (g_sched+gobuf_sp)(BX), DI 146 // make room for sighandler arguments 147 // and re-save old SP for restoring later. 148 // Adjust g0 stack by the space we're using and 149 // save SP at the same place on the g0 stack. 150 // The 40(DI) here must match the 40(SP) above. 151 SUBQ $(REGS_HOST_TO_ABI0_STACK + 48), DI 152 MOVQ SP, 40(DI) 153 MOVQ DI, SP 154 155 g0: 156 MOVQ 0(CX), BX // ExceptionRecord* 157 MOVQ 8(CX), CX // Context* 158 MOVQ BX, 0(SP) 159 MOVQ CX, 8(SP) 160 MOVQ DX, 16(SP) 161 CALL R15 // call handler 162 // AX is set to report result back to Windows 163 MOVL 24(SP), AX 164 165 // switch back to original stack and g 166 // no-op if we never left. 167 MOVQ 40(SP), SP 168 MOVQ 32(SP), DX 169 get_tls(BP) 170 MOVQ DX, g(BP) 171 172 done: 173 ADJSP $-48 174 POP_REGS_HOST_TO_ABI0() 175 176 RET 177 178 TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 179 MOVQ $runtime·exceptionhandler(SB), AX 180 JMP sigtramp<>(SB) 181 182 TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 183 MOVQ $runtime·firstcontinuehandler(SB), AX 184 JMP sigtramp<>(SB) 185 186 TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 187 MOVQ $runtime·lastcontinuehandler(SB), AX 188 JMP sigtramp<>(SB) 189 190 GLOBL runtime·cbctxts(SB), NOPTR, $8 191 192 TEXT runtime·callbackasm1(SB),NOSPLIT,$0 193 // Construct args vector for cgocallback(). 194 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 195 // args from the 5th on are on the stack. 196 // In any case, even if function has 0,1,2,3,4 args, there is reserved 197 // but uninitialized "shadow space" for the first 4 args. 198 // The values are in registers. 199 MOVQ CX, (16+0)(SP) 200 MOVQ DX, (16+8)(SP) 201 MOVQ R8, (16+16)(SP) 202 MOVQ R9, (16+24)(SP) 203 // R8 = address of args vector 204 LEAQ (16+0)(SP), R8 205 206 // remove return address from stack, we are not returning to callbackasm, but to its caller. 207 MOVQ 0(SP), AX 208 ADDQ $8, SP 209 210 // determine index into runtime·cbs table 211 MOVQ $runtime·callbackasm(SB), DX 212 SUBQ DX, AX 213 MOVQ $0, DX 214 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 215 DIVL CX 216 SUBQ $1, AX // subtract 1 because return PC is to the next slot 217 218 // Switch from the host ABI to the Go ABI. 219 PUSH_REGS_HOST_TO_ABI0() 220 221 // Create a struct callbackArgs on our stack to be passed as 222 // the "frame" to cgocallback and on to callbackWrap. 223 SUBQ $(24+callbackArgs__size), SP 224 MOVQ AX, (24+callbackArgs_index)(SP) // callback index 225 MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector 226 MOVQ $0, (24+callbackArgs_result)(SP) // result 227 LEAQ 24(SP), AX 228 // Call cgocallback, which will call callbackWrap(frame). 229 MOVQ $0, 16(SP) // context 230 MOVQ AX, 8(SP) // frame (address of callbackArgs) 231 LEAQ ·callbackWrap<ABIInternal>(SB), BX // cgocallback takes an ABIInternal entry-point 232 MOVQ BX, 0(SP) // PC of function value to call (callbackWrap) 233 CALL ·cgocallback(SB) 234 // Get callback result. 235 MOVQ (24+callbackArgs_result)(SP), AX 236 ADDQ $(24+callbackArgs__size), SP 237 238 POP_REGS_HOST_TO_ABI0() 239 240 // The return value was placed in AX above. 241 RET 242 243 // uint32 tstart_stdcall(M *newm); 244 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 245 // Switch from the host ABI to the Go ABI. 246 PUSH_REGS_HOST_TO_ABI0() 247 248 // CX contains first arg newm 249 MOVQ m_g0(CX), DX // g 250 251 // Layout new m scheduler stack on os stack. 252 MOVQ SP, AX 253 MOVQ AX, (g_stack+stack_hi)(DX) 254 SUBQ $(64*1024), AX // initial stack size (adjusted later) 255 MOVQ AX, (g_stack+stack_lo)(DX) 256 ADDQ $const__StackGuard, AX 257 MOVQ AX, g_stackguard0(DX) 258 MOVQ AX, g_stackguard1(DX) 259 260 // Set up tls. 261 LEAQ m_tls(CX), SI 262 MOVQ SI, 0x28(GS) 263 MOVQ CX, g_m(DX) 264 MOVQ DX, g(SI) 265 266 CALL runtime·stackcheck(SB) // clobbers AX,CX 267 CALL runtime·mstart(SB) 268 269 POP_REGS_HOST_TO_ABI0() 270 271 XORL AX, AX // return 0 == success 272 RET 273 274 // set tls base to DI 275 TEXT runtime·settls(SB),NOSPLIT,$0 276 MOVQ DI, 0x28(GS) 277 RET 278 279 // Runs on OS stack. 280 // duration (in -100ns units) is in dt+0(FP). 281 // g may be nil. 282 // The function leaves room for 4 syscall parameters 283 // (as per windows amd64 calling convention). 284 TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48-4 285 MOVLQSX dt+0(FP), BX 286 MOVQ SP, AX 287 ANDQ $~15, SP // alignment as per Windows requirement 288 MOVQ AX, 40(SP) 289 LEAQ 32(SP), R8 // ptime 290 MOVQ BX, (R8) 291 MOVQ $-1, CX // handle 292 MOVQ $0, DX // alertable 293 MOVQ runtime·_NtWaitForSingleObject(SB), AX 294 CALL AX 295 MOVQ 40(SP), SP 296 RET 297 298 // Runs on OS stack. duration (in -100ns units) is in dt+0(FP). 299 // g is valid. 300 TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72-4 301 MOVLQSX dt+0(FP), BX 302 get_tls(CX) 303 304 MOVQ SP, AX 305 ANDQ $~15, SP // alignment as per Windows requirement 306 MOVQ AX, 64(SP) 307 308 MOVQ g(CX), CX 309 MOVQ g_m(CX), CX 310 MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer 311 MOVQ CX, 48(SP) // save hTimer for later 312 LEAQ 56(SP), DX // lpDueTime 313 MOVQ BX, (DX) 314 MOVQ $0, R8 // lPeriod 315 MOVQ $0, R9 // pfnCompletionRoutine 316 MOVQ $0, AX 317 MOVQ AX, 32(SP) // lpArgToCompletionRoutine 318 MOVQ AX, 40(SP) // fResume 319 MOVQ runtime·_SetWaitableTimer(SB), AX 320 CALL AX 321 322 MOVQ 48(SP), CX // handle 323 MOVQ $0, DX // alertable 324 MOVQ $0, R8 // ptime 325 MOVQ runtime·_NtWaitForSingleObject(SB), AX 326 CALL AX 327 328 MOVQ 64(SP), SP 329 RET 330 331 // Runs on OS stack. 332 TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 333 MOVQ SP, AX 334 ANDQ $~15, SP // alignment as per Windows requirement 335 SUBQ $(48), SP // room for SP and 4 args as per Windows requirement 336 // plus one extra word to keep stack 16 bytes aligned 337 MOVQ AX, 32(SP) 338 MOVQ runtime·_SwitchToThread(SB), AX 339 CALL AX 340 MOVQ 32(SP), SP 341 RET 342 343 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 344 CMPB runtime·useQPCTime(SB), $0 345 JNE useQPC 346 MOVQ $_INTERRUPT_TIME, DI 347 MOVQ time_lo(DI), AX 348 IMULQ $100, AX 349 MOVQ AX, ret+0(FP) 350 RET 351 useQPC: 352 JMP runtime·nanotimeQPC(SB) 353 RET 354 355 // func osSetupTLS(mp *m) 356 // Setup TLS. for use by needm on Windows. 357 TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8 358 MOVQ mp+0(FP), AX 359 LEAQ m_tls(AX), DI 360 CALL runtime·settls(SB) 361 RET