github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/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 9 // maxargs should be divisible by 2, as Windows stack 10 // must be kept 16-byte aligned on syscall entry. 11 #define maxargs 16 12 13 // void runtime·asmstdcall(void *c); 14 TEXT runtime·asmstdcall(SB),NOSPLIT,$0 15 // asmcgocall will put first argument into CX. 16 PUSHQ CX // save for later 17 MOVQ libcall_fn(CX), AX 18 MOVQ libcall_args(CX), SI 19 MOVQ libcall_n(CX), CX 20 21 // SetLastError(0). 22 MOVQ 0x30(GS), DI 23 MOVL $0, 0x68(DI) 24 25 SUBQ $(maxargs*8), SP // room for args 26 27 // Fast version, do not store args on the stack. 28 CMPL CX, $4 29 JLE loadregs 30 31 // Check we have enough room for args. 32 CMPL CX, $maxargs 33 JLE 2(PC) 34 INT $3 // not enough room -> crash 35 36 // Copy args to the stack. 37 MOVQ SP, DI 38 CLD 39 REP; MOVSQ 40 MOVQ SP, SI 41 42 loadregs: 43 // Load first 4 args into correspondent registers. 44 MOVQ 0(SI), CX 45 MOVQ 8(SI), DX 46 MOVQ 16(SI), R8 47 MOVQ 24(SI), R9 48 49 // Call stdcall function. 50 CALL AX 51 52 ADDQ $(maxargs*8), SP 53 54 // Return result. 55 POPQ CX 56 MOVQ AX, libcall_r1(CX) 57 58 // GetLastError(). 59 MOVQ 0x30(GS), DI 60 MOVL 0x68(DI), AX 61 MOVQ AX, libcall_err(CX) 62 63 RET 64 65 TEXT runtime·badsignal2(SB),NOSPLIT,$48 66 // stderr 67 MOVQ $-12, CX // stderr 68 MOVQ CX, 0(SP) 69 MOVQ runtime·_GetStdHandle(SB), AX 70 CALL AX 71 72 MOVQ AX, CX // handle 73 MOVQ CX, 0(SP) 74 MOVQ $runtime·badsignalmsg(SB), DX // pointer 75 MOVQ DX, 8(SP) 76 MOVL $runtime·badsignallen(SB), R8 // count 77 MOVQ R8, 16(SP) 78 LEAQ 40(SP), R9 // written count 79 MOVQ $0, 0(R9) 80 MOVQ R9, 24(SP) 81 MOVQ $0, 32(SP) // overlapped 82 MOVQ runtime·_WriteFile(SB), AX 83 CALL AX 84 85 RET 86 87 // faster get/set last error 88 TEXT runtime·getlasterror(SB),NOSPLIT,$0 89 MOVQ 0x30(GS), AX 90 MOVL 0x68(AX), AX 91 MOVL AX, ret+0(FP) 92 RET 93 94 TEXT runtime·setlasterror(SB),NOSPLIT,$0 95 MOVL err+0(FP), AX 96 MOVQ 0x30(GS), CX 97 MOVL AX, 0x68(CX) 98 RET 99 100 // Called by Windows as a Vectored Exception Handler (VEH). 101 // First argument is pointer to struct containing 102 // exception record and context pointers. 103 // Handler function is stored in AX. 104 // Return 0 for 'not handled', -1 for handled. 105 TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 106 // CX: PEXCEPTION_POINTERS ExceptionInfo 107 108 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved 109 // as required by windows callback convention. 110 PUSHFQ 111 SUBQ $112, SP 112 MOVQ DI, 80(SP) 113 MOVQ SI, 72(SP) 114 MOVQ BP, 64(SP) 115 MOVQ BX, 56(SP) 116 MOVQ R12, 48(SP) 117 MOVQ R13, 40(SP) 118 MOVQ R14, 32(SP) 119 MOVQ R15, 88(SP) 120 121 MOVQ AX, R15 // save handler address 122 123 // find g 124 get_tls(DX) 125 CMPQ DX, $0 126 JNE 3(PC) 127 MOVQ $0, AX // continue 128 JMP done 129 MOVQ g(DX), DX 130 CMPQ DX, $0 131 JNE 2(PC) 132 CALL runtime·badsignal2(SB) 133 134 // save g and SP in case of stack switch 135 MOVQ DX, 96(SP) // g 136 MOVQ SP, 104(SP) 137 138 // do we need to switch to the g0 stack? 139 MOVQ g_m(DX), BX 140 MOVQ m_g0(BX), BX 141 CMPQ DX, BX 142 JEQ g0 143 144 // switch to g0 stack 145 get_tls(BP) 146 MOVQ BX, g(BP) 147 MOVQ (g_sched+gobuf_sp)(BX), DI 148 // make it look like mstart called us on g0, to stop traceback 149 SUBQ $8, DI 150 MOVQ $runtime·mstart(SB), SI 151 MOVQ SI, 0(DI) 152 // traceback will think that we've done PUSHFQ and SUBQ 153 // on this stack, so subtract them here to match. 154 // (we need room for sighandler arguments anyway). 155 // and re-save old SP for restoring later. 156 SUBQ $(112+8), DI 157 // save g, save old stack pointer. 158 MOVQ SP, 104(DI) 159 MOVQ DI, SP 160 161 g0: 162 MOVQ 0(CX), BX // ExceptionRecord* 163 MOVQ 8(CX), CX // Context* 164 MOVQ BX, 0(SP) 165 MOVQ CX, 8(SP) 166 MOVQ DX, 16(SP) 167 CALL R15 // call handler 168 // AX is set to report result back to Windows 169 MOVL 24(SP), AX 170 171 // switch back to original stack and g 172 // no-op if we never left. 173 MOVQ 104(SP), SP 174 MOVQ 96(SP), DX 175 get_tls(BP) 176 MOVQ DX, g(BP) 177 178 done: 179 // restore registers as required for windows callback 180 MOVQ 88(SP), R15 181 MOVQ 32(SP), R14 182 MOVQ 40(SP), R13 183 MOVQ 48(SP), R12 184 MOVQ 56(SP), BX 185 MOVQ 64(SP), BP 186 MOVQ 72(SP), SI 187 MOVQ 80(SP), DI 188 ADDQ $112, SP 189 POPFQ 190 191 RET 192 193 TEXT runtime·exceptiontramp(SB),NOSPLIT,$0 194 MOVQ $runtime·exceptionhandler(SB), AX 195 JMP runtime·sigtramp(SB) 196 197 TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 198 MOVQ $runtime·firstcontinuehandler(SB), AX 199 JMP runtime·sigtramp(SB) 200 201 TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 202 MOVQ $runtime·lastcontinuehandler(SB), AX 203 JMP runtime·sigtramp(SB) 204 205 TEXT runtime·ctrlhandler(SB),NOSPLIT,$8 206 MOVQ CX, 16(SP) // spill 207 MOVQ $runtime·ctrlhandler1(SB), CX 208 MOVQ CX, 0(SP) 209 CALL runtime·externalthreadhandler(SB) 210 RET 211 212 TEXT runtime·profileloop(SB),NOSPLIT,$8 213 MOVQ $runtime·profileloop1(SB), CX 214 MOVQ CX, 0(SP) 215 CALL runtime·externalthreadhandler(SB) 216 RET 217 218 TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 219 PUSHQ BP 220 MOVQ SP, BP 221 PUSHQ BX 222 PUSHQ SI 223 PUSHQ DI 224 PUSHQ 0x28(GS) 225 MOVQ SP, DX 226 227 // setup dummy m, g 228 SUBQ $m__size, SP // space for M 229 MOVQ SP, 0(SP) 230 MOVQ $m__size, 8(SP) 231 CALL runtime·memclr(SB) // smashes AX,BX,CX 232 233 LEAQ m_tls(SP), CX 234 MOVQ CX, 0x28(GS) 235 MOVQ SP, BX 236 SUBQ $g__size, SP // space for G 237 MOVQ SP, g(CX) 238 MOVQ SP, m_g0(BX) 239 240 MOVQ SP, 0(SP) 241 MOVQ $g__size, 8(SP) 242 CALL runtime·memclr(SB) // smashes AX,BX,CX 243 LEAQ g__size(SP), BX 244 MOVQ BX, g_m(SP) 245 246 LEAQ -8192(SP), CX 247 MOVQ CX, (g_stack+stack_lo)(SP) 248 ADDQ $const__StackGuard, CX 249 MOVQ CX, g_stackguard0(SP) 250 MOVQ CX, g_stackguard1(SP) 251 MOVQ DX, (g_stack+stack_hi)(SP) 252 253 PUSHQ 32(BP) // arg for handler 254 CALL 16(BP) 255 POPQ CX 256 257 get_tls(CX) 258 MOVQ g(CX), CX 259 MOVQ (g_stack+stack_hi)(CX), SP 260 POPQ 0x28(GS) 261 POPQ DI 262 POPQ SI 263 POPQ BX 264 POPQ BP 265 RET 266 267 GLOBL runtime·cbctxts(SB), NOPTR, $8 268 269 TEXT runtime·callbackasm1(SB),NOSPLIT,$0 270 // Construct args vector for cgocallback(). 271 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 272 // args from the 5th on are on the stack. 273 // In any case, even if function has 0,1,2,3,4 args, there is reserved 274 // but uninitialized "shadow space" for the first 4 args. 275 // The values are in registers. 276 MOVQ CX, (16+0)(SP) 277 MOVQ DX, (16+8)(SP) 278 MOVQ R8, (16+16)(SP) 279 MOVQ R9, (16+24)(SP) 280 281 // remove return address from stack, we are not returning there 282 MOVQ 0(SP), AX 283 ADDQ $8, SP 284 285 // determine index into runtime·cbctxts table 286 MOVQ $runtime·callbackasm(SB), DX 287 SUBQ DX, AX 288 MOVQ $0, DX 289 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 290 DIVL CX, 291 292 // find correspondent runtime·cbctxts table entry 293 MOVQ runtime·cbctxts(SB), CX 294 MOVQ -8(CX)(AX*8), AX 295 296 // extract callback context 297 MOVQ wincallbackcontext_argsize(AX), DX 298 MOVQ wincallbackcontext_gobody(AX), AX 299 300 // preserve whatever's at the memory location that 301 // the callback will use to store the return value 302 LEAQ 8(SP), CX // args vector, skip return address 303 PUSHQ 0(CX)(DX*1) // store 8 bytes from just after the args array 304 ADDQ $8, DX // extend argsize by size of return value 305 306 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved 307 // as required by windows callback convention. 308 PUSHFQ 309 SUBQ $64, SP 310 MOVQ DI, 56(SP) 311 MOVQ SI, 48(SP) 312 MOVQ BP, 40(SP) 313 MOVQ BX, 32(SP) 314 MOVQ R12, 24(SP) 315 MOVQ R13, 16(SP) 316 MOVQ R14, 8(SP) 317 MOVQ R15, 0(SP) 318 319 // prepare call stack. use SUBQ to hide from stack frame checks 320 // cgocallback(Go func, void *frame, uintptr framesize) 321 SUBQ $24, SP 322 MOVQ DX, 16(SP) // argsize (including return value) 323 MOVQ CX, 8(SP) // callback parameters 324 MOVQ AX, 0(SP) // address of target Go function 325 CLD 326 CALL runtime·cgocallback_gofunc(SB) 327 MOVQ 0(SP), AX 328 MOVQ 8(SP), CX 329 MOVQ 16(SP), DX 330 ADDQ $24, SP 331 332 // restore registers as required for windows callback 333 MOVQ 0(SP), R15 334 MOVQ 8(SP), R14 335 MOVQ 16(SP), R13 336 MOVQ 24(SP), R12 337 MOVQ 32(SP), BX 338 MOVQ 40(SP), BP 339 MOVQ 48(SP), SI 340 MOVQ 56(SP), DI 341 ADDQ $64, SP 342 POPFQ 343 344 MOVL -8(CX)(DX*1), AX // return value 345 POPQ -8(CX)(DX*1) // restore bytes just after the args 346 RET 347 348 // uint32 tstart_stdcall(M *newm); 349 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 350 // CX contains first arg newm 351 MOVQ m_g0(CX), DX // g 352 353 // Layout new m scheduler stack on os stack. 354 MOVQ SP, AX 355 MOVQ AX, (g_stack+stack_hi)(DX) 356 SUBQ $(64*1024), AX // stack size 357 MOVQ AX, (g_stack+stack_lo)(DX) 358 ADDQ $const__StackGuard, AX 359 MOVQ AX, g_stackguard0(DX) 360 MOVQ AX, g_stackguard1(DX) 361 362 // Set up tls. 363 LEAQ m_tls(CX), SI 364 MOVQ SI, 0x28(GS) 365 MOVQ CX, g_m(DX) 366 MOVQ DX, g(SI) 367 368 // Someday the convention will be D is always cleared. 369 CLD 370 371 CALL runtime·stackcheck(SB) // clobbers AX,CX 372 CALL runtime·mstart(SB) 373 374 XORL AX, AX // return 0 == success 375 RET 376 377 // set tls base to DI 378 TEXT runtime·settls(SB),NOSPLIT,$0 379 MOVQ DI, 0x28(GS) 380 RET 381 382 // Sleep duration is in 100ns units. 383 TEXT runtime·usleep1(SB),NOSPLIT,$0 384 MOVL usec+0(FP), BX 385 MOVQ $runtime·usleep2(SB), AX // to hide from 6l 386 387 // Execute call on m->g0 stack, in case we are not actually 388 // calling a system call wrapper, like when running under WINE. 389 get_tls(R15) 390 CMPQ R15, $0 391 JNE 3(PC) 392 // Not a Go-managed thread. Do not switch stack. 393 CALL AX 394 RET 395 396 MOVQ g(R15), R13 397 MOVQ g_m(R13), R13 398 399 // leave pc/sp for cpu profiler 400 MOVQ (SP), R12 401 MOVQ R12, m_libcallpc(R13) 402 MOVQ g(R15), R12 403 MOVQ R12, m_libcallg(R13) 404 // sp must be the last, because once async cpu profiler finds 405 // all three values to be non-zero, it will use them 406 LEAQ usec+0(FP), R12 407 MOVQ R12, m_libcallsp(R13) 408 409 MOVQ m_g0(R13), R14 410 CMPQ g(R15), R14 411 JNE switch 412 // executing on m->g0 already 413 CALL AX 414 JMP ret 415 416 switch: 417 // Switch to m->g0 stack and back. 418 MOVQ (g_sched+gobuf_sp)(R14), R14 419 MOVQ SP, -8(R14) 420 LEAQ -8(R14), SP 421 CALL AX 422 MOVQ 0(SP), SP 423 424 ret: 425 MOVQ $0, m_libcallsp(R13) 426 RET 427 428 // Runs on OS stack. duration (in 100ns units) is in BX. 429 TEXT runtime·usleep2(SB),NOSPLIT,$16 430 MOVQ SP, AX 431 ANDQ $~15, SP // alignment as per Windows requirement 432 MOVQ AX, 8(SP) 433 // Want negative 100ns units. 434 NEGQ BX 435 MOVQ SP, R8 // ptime 436 MOVQ BX, (R8) 437 MOVQ $-1, CX // handle 438 MOVQ $0, DX // alertable 439 MOVQ runtime·_NtWaitForSingleObject(SB), AX 440 CALL AX 441 MOVQ 8(SP), SP 442 RET 443 444 // func now() (sec int64, nsec int32) 445 TEXT time·now(SB),NOSPLIT,$8-12 446 CALL runtime·unixnano(SB) 447 MOVQ 0(SP), AX 448 449 // generated code for 450 // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } 451 // adapted to reduce duplication 452 MOVQ AX, CX 453 MOVQ $1360296554856532783, AX 454 MULQ CX 455 ADDQ CX, DX 456 RCRQ $1, DX 457 SHRQ $29, DX 458 MOVQ DX, sec+0(FP) 459 IMULQ $1000000000, DX 460 SUBQ DX, CX 461 MOVL CX, nsec+8(FP) 462 RET 463