github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/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 "zasm_GOOS_GOARCH.h" 6 7 // maxargs should be divisible by 2, as Windows stack 8 // must be kept 16-byte aligned on syscall entry. 9 #define maxargs 16 10 11 // void runtime·asmstdcall(void *c); 12 TEXT runtime·asmstdcall(SB),7,$0 13 // asmcgocall will put first argument into CX. 14 PUSHQ CX // save for later 15 MOVQ wincall_fn(CX), AX 16 MOVQ wincall_args(CX), SI 17 MOVQ wincall_n(CX), CX 18 19 // SetLastError(0). 20 MOVQ 0x30(GS), DI 21 MOVL $0, 0x68(DI) 22 23 SUBQ $(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, $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 47 // Call stdcall function. 48 CALL AX 49 50 ADDQ $(maxargs*8), SP 51 52 // Return result. 53 POPQ CX 54 MOVQ AX, wincall_r1(CX) 55 56 // GetLastError(). 57 MOVQ 0x30(GS), DI 58 MOVL 0x68(DI), AX 59 MOVQ AX, wincall_err(CX) 60 61 RET 62 63 // This should be called on a system stack, 64 // so we don't need to concern about split stack. 65 TEXT runtime·badcallback(SB),7,$0 66 SUBQ $48, SP 67 68 // stderr 69 MOVQ $-12, CX // stderr 70 MOVQ CX, 0(SP) 71 MOVQ runtime·GetStdHandle(SB), AX 72 CALL AX 73 74 MOVQ AX, CX // handle 75 MOVQ CX, 0(SP) 76 MOVQ $runtime·badcallbackmsg(SB), DX // pointer 77 MOVQ DX, 8(SP) 78 MOVL $runtime·badcallbacklen(SB), R8 // count 79 MOVQ R8, 16(SP) 80 LEAQ 40(SP), R9 // written count 81 MOVQ $0, 0(R9) 82 MOVQ R9, 24(SP) 83 MOVQ $0, 32(SP) // overlapped 84 MOVQ runtime·WriteFile(SB), AX 85 CALL AX 86 87 ADDQ $48, SP 88 RET 89 90 TEXT runtime·badsignal(SB),7,$48 91 // stderr 92 MOVQ $-12, CX // stderr 93 MOVQ CX, 0(SP) 94 MOVQ runtime·GetStdHandle(SB), AX 95 CALL AX 96 97 MOVQ AX, CX // handle 98 MOVQ CX, 0(SP) 99 MOVQ $runtime·badsignalmsg(SB), DX // pointer 100 MOVQ DX, 8(SP) 101 MOVL $runtime·badsignallen(SB), R8 // count 102 MOVQ R8, 16(SP) 103 LEAQ 40(SP), R9 // written count 104 MOVQ $0, 0(R9) 105 MOVQ R9, 24(SP) 106 MOVQ $0, 32(SP) // overlapped 107 MOVQ runtime·WriteFile(SB), AX 108 CALL AX 109 110 RET 111 112 // faster get/set last error 113 TEXT runtime·getlasterror(SB),7,$0 114 MOVQ 0x30(GS), AX 115 MOVL 0x68(AX), AX 116 RET 117 118 TEXT runtime·setlasterror(SB),7,$0 119 MOVL err+0(FP), AX 120 MOVQ 0x30(GS), CX 121 MOVL AX, 0x68(CX) 122 RET 123 124 TEXT runtime·sigtramp(SB),7,$0 125 // CX: exception record 126 // R8: context 127 128 // unwinding? 129 TESTL $6, 4(CX) // exception flags 130 MOVL $1, AX 131 JNZ sigdone 132 133 // copy arguments for call to sighandler. 134 135 // Stack adjustment is here to hide from 6l, 136 // which doesn't understand that sigtramp 137 // runs on essentially unlimited stack. 138 SUBQ $56, SP 139 MOVQ CX, 0(SP) 140 MOVQ R8, 8(SP) 141 142 get_tls(CX) 143 144 // check that m exists 145 MOVQ m(CX), AX 146 CMPQ AX, $0 147 JNE 2(PC) 148 CALL runtime·badsignal(SB) 149 150 MOVQ g(CX), CX 151 MOVQ CX, 16(SP) 152 153 MOVQ BX, 24(SP) 154 MOVQ BP, 32(SP) 155 MOVQ SI, 40(SP) 156 MOVQ DI, 48(SP) 157 158 CALL runtime·sighandler(SB) 159 160 MOVQ 24(SP), BX 161 MOVQ 32(SP), BP 162 MOVQ 40(SP), SI 163 MOVQ 48(SP), DI 164 ADDQ $56, SP 165 166 sigdone: 167 RET 168 169 TEXT runtime·ctrlhandler(SB),7,$8 170 MOVQ CX, 16(SP) // spill 171 MOVQ $runtime·ctrlhandler1(SB), CX 172 MOVQ CX, 0(SP) 173 CALL runtime·externalthreadhandler(SB) 174 RET 175 176 TEXT runtime·profileloop(SB),7,$8 177 MOVQ $runtime·profileloop1(SB), CX 178 MOVQ CX, 0(SP) 179 CALL runtime·externalthreadhandler(SB) 180 RET 181 182 TEXT runtime·externalthreadhandler(SB),7,$0 183 PUSHQ BP 184 MOVQ SP, BP 185 PUSHQ BX 186 PUSHQ SI 187 PUSHQ DI 188 PUSHQ 0x28(GS) 189 MOVQ SP, DX 190 191 // setup dummy m, g 192 SUBQ $m_end, SP // space for M 193 MOVQ SP, 0(SP) 194 MOVQ $m_end, 8(SP) 195 CALL runtime·memclr(SB) // smashes AX,BX,CX 196 197 LEAQ m_tls(SP), CX 198 MOVQ CX, 0x28(GS) 199 MOVQ SP, m(CX) 200 MOVQ SP, BX 201 SUBQ $g_end, SP // space for G 202 MOVQ SP, g(CX) 203 MOVQ SP, m_g0(BX) 204 205 MOVQ SP, 0(SP) 206 MOVQ $g_end, 8(SP) 207 CALL runtime·memclr(SB) // smashes AX,BX,CX 208 LEAQ -8192(SP), CX 209 MOVQ CX, g_stackguard(SP) 210 MOVQ DX, g_stackbase(SP) 211 212 PUSHQ 32(BP) // arg for handler 213 CALL 16(BP) 214 POPQ CX 215 216 get_tls(CX) 217 MOVQ g(CX), CX 218 MOVQ g_stackbase(CX), SP 219 POPQ 0x28(GS) 220 POPQ DI 221 POPQ SI 222 POPQ BX 223 POPQ BP 224 RET 225 226 // Continuation of thunk function created for each callback by ../thread.c compilecallback, 227 // runs on Windows stack (not Go stack). 228 // Thunk code designed to have minimal size for it is copied many (up to thousands) times. 229 // 230 // thunk: 231 // MOVQ $fn, AX 232 // PUSHQ AX 233 // MOVQ $argsize, AX 234 // PUSHQ AX 235 // MOVQ $runtime·callbackasm, AX 236 // JMP AX 237 TEXT runtime·callbackasm(SB),7,$0 238 // Construct args vector for cgocallback(). 239 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 240 // args from the 5th on are on the stack. 241 // In any case, even if function has 0,1,2,3,4 args, there is reserved 242 // but uninitialized "shadow space" for the first 4 args. 243 // The values are in registers. 244 MOVQ CX, (24+0)(SP) 245 MOVQ DX, (24+8)(SP) 246 MOVQ R8, (24+16)(SP) 247 MOVQ R9, (24+24)(SP) 248 // 6l does not accept writing POPQs here issuing a warning "unbalanced PUSH/POP" 249 MOVQ 0(SP), DX // POPQ DX 250 MOVQ 8(SP), AX // POPQ AX 251 ADDQ $16, SP 252 253 // preserve whatever's at the memory location that 254 // the callback will use to store the return value 255 LEAQ 8(SP), CX // args vector, skip return address 256 PUSHQ 0(CX)(DX*1) // store 8 bytes from just after the args array 257 ADDQ $8, DX // extend argsize by size of return value 258 259 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved 260 // as required by windows callback convention. 261 // 6l does not allow writing many PUSHQs here issuing a warning "nosplit stack overflow" 262 // the warning has no sense as this code uses os thread stack 263 PUSHFQ 264 SUBQ $64, SP 265 MOVQ DI, 56(SP) 266 MOVQ SI, 48(SP) 267 MOVQ BP, 40(SP) 268 MOVQ BX, 32(SP) 269 MOVQ R12, 24(SP) 270 MOVQ R13, 16(SP) 271 MOVQ R14, 8(SP) 272 MOVQ R15, 0(SP) 273 274 // prepare call stack. use SUBQ to hide from stack frame checks 275 // cgocallback(Go func, void *frame, uintptr framesize) 276 SUBQ $24, SP 277 MOVQ DX, 16(SP) // uintptr framesize 278 MOVQ CX, 8(SP) // void *frame 279 MOVQ AX, 0(SP) // Go func 280 CLD 281 CALL runtime·cgocallback_gofunc(SB) 282 MOVQ 0(SP), AX 283 MOVQ 8(SP), CX 284 MOVQ 16(SP), DX 285 ADDQ $24, SP 286 287 // restore registers as required for windows callback 288 // 6l does not allow writing many POPs here issuing a warning "nosplit stack overflow" 289 MOVQ 0(SP), R15 290 MOVQ 8(SP), R14 291 MOVQ 16(SP), R13 292 MOVQ 24(SP), R12 293 MOVQ 32(SP), BX 294 MOVQ 40(SP), BP 295 MOVQ 48(SP), SI 296 MOVQ 56(SP), DI 297 ADDQ $64, SP 298 POPFQ 299 300 MOVL -8(CX)(DX*1), AX // return value 301 POPQ -8(CX)(DX*1) // restore bytes just after the args 302 RET 303 304 TEXT runtime·setstacklimits(SB),7,$0 305 MOVQ 0x30(GS), CX 306 MOVQ $0, 0x10(CX) 307 MOVQ $0xffffffffffff, AX 308 MOVQ AX, 0x08(CX) 309 RET 310 311 // uint32 tstart_stdcall(M *newm); 312 TEXT runtime·tstart_stdcall(SB),7,$0 313 // CX contains first arg newm 314 MOVQ m_g0(CX), DX // g 315 316 // Layout new m scheduler stack on os stack. 317 MOVQ SP, AX 318 MOVQ AX, g_stackbase(DX) 319 SUBQ $(64*1024), AX // stack size 320 MOVQ AX, g_stackguard(DX) 321 322 // Set up tls. 323 LEAQ m_tls(CX), SI 324 MOVQ SI, 0x28(GS) 325 MOVQ CX, m(SI) 326 MOVQ DX, g(SI) 327 328 // Someday the convention will be D is always cleared. 329 CLD 330 331 CALL runtime·stackcheck(SB) // clobbers AX,CX 332 CALL runtime·mstart(SB) 333 334 XORL AX, AX // return 0 == success 335 RET 336 337 // set tls base to DI 338 TEXT runtime·settls(SB),7,$0 339 MOVQ DI, 0x28(GS) 340 RET 341 342 // void install_exception_handler() 343 TEXT runtime·install_exception_handler(SB),7,$0 344 CALL runtime·setstacklimits(SB) 345 RET 346 347 TEXT runtime·remove_exception_handler(SB),7,$0 348 RET 349 350 TEXT runtime·osyield(SB),7,$8 351 // Tried NtYieldExecution but it doesn't yield hard enough. 352 // NtWaitForSingleObject being used here as Sleep(0). 353 // The CALL is safe because NtXxx is a system call wrapper: 354 // it puts the right system call number in AX, then does 355 // a SYSENTER and a RET. 356 MOVQ runtime·NtWaitForSingleObject(SB), AX 357 MOVQ $1, BX 358 NEGQ BX 359 MOVQ SP, R8 // ptime 360 MOVQ BX, (R8) 361 MOVQ $-1, CX // handle 362 MOVQ $0, DX // alertable 363 CALL AX 364 RET 365 366 TEXT runtime·usleep(SB),7,$8 367 // The CALL is safe because NtXxx is a system call wrapper: 368 // it puts the right system call number in AX, then does 369 // a SYSENTER and a RET. 370 MOVQ runtime·NtWaitForSingleObject(SB), AX 371 // Have 1us units; want negative 100ns units. 372 MOVL usec+0(FP), BX 373 IMULQ $10, BX 374 NEGQ BX 375 MOVQ SP, R8 // ptime 376 MOVQ BX, (R8) 377 MOVQ $-1, CX // handle 378 MOVQ $0, DX // alertable 379 CALL AX 380 RET