github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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 #include "../../cmd/ld/textflag.h" 7 8 // maxargs should be divisible by 2, as Windows stack 9 // must be kept 16-byte aligned on syscall entry. 10 #define maxargs 16 11 12 // void runtime·asmstdcall(void *c); 13 TEXT runtime·asmstdcall(SB),NOSPLIT,$0 14 // asmcgocall will put first argument into CX. 15 PUSHQ CX // save for later 16 MOVQ wincall_fn(CX), AX 17 MOVQ wincall_args(CX), SI 18 MOVQ wincall_n(CX), CX 19 20 // SetLastError(0). 21 MOVQ 0x30(GS), DI 22 MOVL $0, 0x68(DI) 23 24 SUBQ $(maxargs*8), SP // room for args 25 26 // Fast version, do not store args on the stack. 27 CMPL CX, $4 28 JLE loadregs 29 30 // Check we have enough room for args. 31 CMPL CX, $maxargs 32 JLE 2(PC) 33 INT $3 // not enough room -> crash 34 35 // Copy args to the stack. 36 MOVQ SP, DI 37 CLD 38 REP; MOVSQ 39 MOVQ SP, SI 40 41 loadregs: 42 // Load first 4 args into correspondent registers. 43 MOVQ 0(SI), CX 44 MOVQ 8(SI), DX 45 MOVQ 16(SI), R8 46 MOVQ 24(SI), R9 47 48 // Call stdcall function. 49 CALL AX 50 51 ADDQ $(maxargs*8), SP 52 53 // Return result. 54 POPQ CX 55 MOVQ AX, wincall_r1(CX) 56 57 // GetLastError(). 58 MOVQ 0x30(GS), DI 59 MOVL 0x68(DI), AX 60 MOVQ AX, wincall_err(CX) 61 62 RET 63 64 TEXT runtime·badsignal2(SB),NOSPLIT,$48 65 // stderr 66 MOVQ $-12, CX // stderr 67 MOVQ CX, 0(SP) 68 MOVQ runtime·GetStdHandle(SB), AX 69 CALL AX 70 71 MOVQ AX, CX // handle 72 MOVQ CX, 0(SP) 73 MOVQ $runtime·badsignalmsg(SB), DX // pointer 74 MOVQ DX, 8(SP) 75 MOVL $runtime·badsignallen(SB), R8 // count 76 MOVQ R8, 16(SP) 77 LEAQ 40(SP), R9 // written count 78 MOVQ $0, 0(R9) 79 MOVQ R9, 24(SP) 80 MOVQ $0, 32(SP) // overlapped 81 MOVQ runtime·WriteFile(SB), AX 82 CALL AX 83 84 RET 85 86 // faster get/set last error 87 TEXT runtime·getlasterror(SB),NOSPLIT,$0 88 MOVQ 0x30(GS), AX 89 MOVL 0x68(AX), AX 90 RET 91 92 TEXT runtime·setlasterror(SB),NOSPLIT,$0 93 MOVL err+0(FP), AX 94 MOVQ 0x30(GS), CX 95 MOVL AX, 0x68(CX) 96 RET 97 98 TEXT runtime·sigtramp(SB),NOSPLIT,$0 99 // CX: exception record 100 // R8: context 101 102 // unwinding? 103 TESTL $6, 4(CX) // exception flags 104 MOVL $1, AX 105 JNZ sigdone 106 107 // copy arguments for call to sighandler. 108 109 // Stack adjustment is here to hide from 6l, 110 // which doesn't understand that sigtramp 111 // runs on essentially unlimited stack. 112 SUBQ $56, SP 113 MOVQ CX, 0(SP) 114 MOVQ R8, 8(SP) 115 116 get_tls(CX) 117 118 // check that m exists 119 MOVQ m(CX), AX 120 CMPQ AX, $0 121 JNE 2(PC) 122 CALL runtime·badsignal2(SB) 123 124 MOVQ g(CX), CX 125 MOVQ CX, 16(SP) 126 127 MOVQ BX, 24(SP) 128 MOVQ BP, 32(SP) 129 MOVQ SI, 40(SP) 130 MOVQ DI, 48(SP) 131 132 CALL runtime·sighandler(SB) 133 134 MOVQ 24(SP), BX 135 MOVQ 32(SP), BP 136 MOVQ 40(SP), SI 137 MOVQ 48(SP), DI 138 ADDQ $56, SP 139 140 sigdone: 141 RET 142 143 TEXT runtime·ctrlhandler(SB),NOSPLIT,$8 144 MOVQ CX, 16(SP) // spill 145 MOVQ $runtime·ctrlhandler1(SB), CX 146 MOVQ CX, 0(SP) 147 CALL runtime·externalthreadhandler(SB) 148 RET 149 150 TEXT runtime·profileloop(SB),NOSPLIT,$8 151 MOVQ $runtime·profileloop1(SB), CX 152 MOVQ CX, 0(SP) 153 CALL runtime·externalthreadhandler(SB) 154 RET 155 156 TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 157 PUSHQ BP 158 MOVQ SP, BP 159 PUSHQ BX 160 PUSHQ SI 161 PUSHQ DI 162 PUSHQ 0x28(GS) 163 MOVQ SP, DX 164 165 // setup dummy m, g 166 SUBQ $m_end, SP // space for M 167 MOVQ SP, 0(SP) 168 MOVQ $m_end, 8(SP) 169 CALL runtime·memclr(SB) // smashes AX,BX,CX 170 171 LEAQ m_tls(SP), CX 172 MOVQ CX, 0x28(GS) 173 MOVQ SP, m(CX) 174 MOVQ SP, BX 175 SUBQ $g_end, SP // space for G 176 MOVQ SP, g(CX) 177 MOVQ SP, m_g0(BX) 178 179 MOVQ SP, 0(SP) 180 MOVQ $g_end, 8(SP) 181 CALL runtime·memclr(SB) // smashes AX,BX,CX 182 LEAQ -8192(SP), CX 183 MOVQ CX, g_stackguard(SP) 184 MOVQ DX, g_stackbase(SP) 185 186 PUSHQ 32(BP) // arg for handler 187 CALL 16(BP) 188 POPQ CX 189 190 get_tls(CX) 191 MOVQ g(CX), CX 192 MOVQ g_stackbase(CX), SP 193 POPQ 0x28(GS) 194 POPQ DI 195 POPQ SI 196 POPQ BX 197 POPQ BP 198 RET 199 200 GLOBL runtime·cbctxts(SB), $8 201 202 TEXT runtime·callbackasm1(SB),NOSPLIT,$0 203 // Construct args vector for cgocallback(). 204 // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 205 // args from the 5th on are on the stack. 206 // In any case, even if function has 0,1,2,3,4 args, there is reserved 207 // but uninitialized "shadow space" for the first 4 args. 208 // The values are in registers. 209 MOVQ CX, (16+0)(SP) 210 MOVQ DX, (16+8)(SP) 211 MOVQ R8, (16+16)(SP) 212 MOVQ R9, (16+24)(SP) 213 214 // remove return address from stack, we are not returning there 215 MOVQ 0(SP), AX 216 ADDQ $8, SP 217 218 // determine index into runtime·cbctxts table 219 SUBQ $runtime·callbackasm(SB), AX 220 MOVQ $0, DX 221 MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 222 DIVL CX, 223 224 // find correspondent runtime·cbctxts table entry 225 MOVQ runtime·cbctxts(SB), CX 226 MOVQ -8(CX)(AX*8), AX 227 228 // extract callback context 229 MOVQ cbctxt_argsize(AX), DX 230 MOVQ cbctxt_gobody(AX), AX 231 232 // preserve whatever's at the memory location that 233 // the callback will use to store the return value 234 LEAQ 8(SP), CX // args vector, skip return address 235 PUSHQ 0(CX)(DX*1) // store 8 bytes from just after the args array 236 ADDQ $8, DX // extend argsize by size of return value 237 238 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved 239 // as required by windows callback convention. 240 PUSHFQ 241 SUBQ $64, SP 242 MOVQ DI, 56(SP) 243 MOVQ SI, 48(SP) 244 MOVQ BP, 40(SP) 245 MOVQ BX, 32(SP) 246 MOVQ R12, 24(SP) 247 MOVQ R13, 16(SP) 248 MOVQ R14, 8(SP) 249 MOVQ R15, 0(SP) 250 251 // prepare call stack. use SUBQ to hide from stack frame checks 252 // cgocallback(Go func, void *frame, uintptr framesize) 253 SUBQ $24, SP 254 MOVQ DX, 16(SP) // argsize (including return value) 255 MOVQ CX, 8(SP) // callback parameters 256 MOVQ AX, 0(SP) // address of target Go function 257 CLD 258 CALL runtime·cgocallback_gofunc(SB) 259 MOVQ 0(SP), AX 260 MOVQ 8(SP), CX 261 MOVQ 16(SP), DX 262 ADDQ $24, SP 263 264 // restore registers as required for windows callback 265 MOVQ 0(SP), R15 266 MOVQ 8(SP), R14 267 MOVQ 16(SP), R13 268 MOVQ 24(SP), R12 269 MOVQ 32(SP), BX 270 MOVQ 40(SP), BP 271 MOVQ 48(SP), SI 272 MOVQ 56(SP), DI 273 ADDQ $64, SP 274 POPFQ 275 276 MOVL -8(CX)(DX*1), AX // return value 277 POPQ -8(CX)(DX*1) // restore bytes just after the args 278 RET 279 280 TEXT runtime·setstacklimits(SB),NOSPLIT,$0 281 MOVQ 0x30(GS), CX 282 MOVQ $0, 0x10(CX) 283 MOVQ $0xffffffffffff, AX 284 MOVQ AX, 0x08(CX) 285 RET 286 287 // uint32 tstart_stdcall(M *newm); 288 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 289 // CX contains first arg newm 290 MOVQ m_g0(CX), DX // g 291 292 // Layout new m scheduler stack on os stack. 293 MOVQ SP, AX 294 MOVQ AX, g_stackbase(DX) 295 SUBQ $(64*1024), AX // stack size 296 MOVQ AX, g_stackguard(DX) 297 298 // Set up tls. 299 LEAQ m_tls(CX), SI 300 MOVQ SI, 0x28(GS) 301 MOVQ CX, m(SI) 302 MOVQ DX, g(SI) 303 304 // Someday the convention will be D is always cleared. 305 CLD 306 307 CALL runtime·stackcheck(SB) // clobbers AX,CX 308 CALL runtime·mstart(SB) 309 310 XORL AX, AX // return 0 == success 311 RET 312 313 // set tls base to DI 314 TEXT runtime·settls(SB),NOSPLIT,$0 315 MOVQ DI, 0x28(GS) 316 RET 317 318 // void install_exception_handler() 319 TEXT runtime·install_exception_handler(SB),NOSPLIT,$0 320 CALL runtime·setstacklimits(SB) 321 RET 322 323 TEXT runtime·remove_exception_handler(SB),NOSPLIT,$0 324 RET 325 326 // Sleep duration is in 100ns units. 327 TEXT runtime·usleep1(SB),NOSPLIT,$0 328 MOVL duration+0(FP), BX 329 MOVQ $runtime·usleep2(SB), AX // to hide from 6l 330 331 // Execute call on m->g0 stack, in case we are not actually 332 // calling a system call wrapper, like when running under WINE. 333 get_tls(R15) 334 CMPQ R15, $0 335 JNE 3(PC) 336 // Not a Go-managed thread. Do not switch stack. 337 CALL AX 338 RET 339 340 MOVQ m(R15), R14 341 MOVQ m_g0(R14), R14 342 CMPQ g(R15), R14 343 JNE 3(PC) 344 // executing on m->g0 already 345 CALL AX 346 RET 347 348 // Switch to m->g0 stack and back. 349 MOVQ (g_sched+gobuf_sp)(R14), R14 350 MOVQ SP, -8(R14) 351 LEAQ -8(R14), SP 352 CALL AX 353 MOVQ 0(SP), SP 354 RET 355 356 // Runs on OS stack. duration (in 100ns units) is in BX. 357 TEXT runtime·usleep2(SB),NOSPLIT,$8 358 // Want negative 100ns units. 359 NEGQ BX 360 MOVQ SP, R8 // ptime 361 MOVQ BX, (R8) 362 MOVQ $-1, CX // handle 363 MOVQ $0, DX // alertable 364 MOVQ runtime·NtWaitForSingleObject(SB), AX 365 CALL AX 366 RET