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