github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/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·memclrNoHeapPointers(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·memclrNoHeapPointers(SB) // smashes AX,BX,CX 207 LEAL g__size(SP), BX 208 MOVL BX, g_m(SP) 209 210 LEAL -32768(SP), CX // must be less than SizeOfStackReserve set by linker 211 MOVL CX, (g_stack+stack_lo)(SP) 212 ADDL $const__StackGuard, CX 213 MOVL CX, g_stackguard0(SP) 214 MOVL CX, g_stackguard1(SP) 215 MOVL DX, (g_stack+stack_hi)(SP) 216 217 PUSHL AX // room for return value 218 PUSHL 16(BP) // arg for handler 219 CALL 8(BP) 220 POPL CX 221 POPL AX // pass return value to Windows in AX 222 223 get_tls(CX) 224 MOVL g(CX), CX 225 MOVL (g_stack+stack_hi)(CX), SP 226 POPL 0x14(FS) 227 POPL DI 228 POPL SI 229 POPL BX 230 POPL BP 231 RET 232 233 GLOBL runtime·cbctxts(SB), NOPTR, $4 234 235 TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0 236 MOVL 0(SP), AX // will use to find our callback context 237 238 // remove return address from stack, we are not returning there 239 ADDL $4, SP 240 241 // address to callback parameters into CX 242 LEAL 4(SP), CX 243 244 // save registers as required for windows callback 245 PUSHL DI 246 PUSHL SI 247 PUSHL BP 248 PUSHL BX 249 250 // determine index into runtime·cbctxts table 251 SUBL $runtime·callbackasm(SB), AX 252 MOVL $0, DX 253 MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 254 DIVL BX 255 256 // find correspondent runtime·cbctxts table entry 257 MOVL runtime·cbctxts(SB), BX 258 MOVL -4(BX)(AX*4), BX 259 260 // extract callback context 261 MOVL wincallbackcontext_gobody(BX), AX 262 MOVL wincallbackcontext_argsize(BX), DX 263 264 // preserve whatever's at the memory location that 265 // the callback will use to store the return value 266 PUSHL 0(CX)(DX*1) 267 268 // extend argsize by size of return value 269 ADDL $4, DX 270 271 // remember how to restore stack on return 272 MOVL wincallbackcontext_restorestack(BX), BX 273 PUSHL BX 274 275 // call target Go function 276 PUSHL DX // argsize (including return value) 277 PUSHL CX // callback parameters 278 PUSHL AX // address of target Go function 279 CLD 280 CALL runtime·cgocallback_gofunc(SB) 281 POPL AX 282 POPL CX 283 POPL DX 284 285 // how to restore stack on return 286 POPL BX 287 288 // return value into AX (as per Windows spec) 289 // and restore previously preserved value 290 MOVL -4(CX)(DX*1), AX 291 POPL -4(CX)(DX*1) 292 293 MOVL BX, CX // cannot use BX anymore 294 295 // restore registers as required for windows callback 296 POPL BX 297 POPL BP 298 POPL SI 299 POPL DI 300 301 // remove callback parameters before return (as per Windows spec) 302 POPL DX 303 ADDL CX, SP 304 PUSHL DX 305 306 CLD 307 308 RET 309 310 // void tstart(M *newm); 311 TEXT runtime·tstart(SB),NOSPLIT,$0 312 MOVL newm+0(FP), CX // m 313 MOVL m_g0(CX), DX // g 314 315 // Layout new m scheduler stack on os stack. 316 MOVL SP, AX 317 MOVL AX, (g_stack+stack_hi)(DX) 318 SUBL $(64*1024), AX // stack size 319 MOVL AX, (g_stack+stack_lo)(DX) 320 ADDL $const__StackGuard, AX 321 MOVL AX, g_stackguard0(DX) 322 MOVL AX, g_stackguard1(DX) 323 324 // Set up tls. 325 LEAL m_tls(CX), SI 326 MOVL SI, 0x14(FS) 327 MOVL CX, g_m(DX) 328 MOVL DX, g(SI) 329 330 // Someday the convention will be D is always cleared. 331 CLD 332 333 CALL runtime·stackcheck(SB) // clobbers AX,CX 334 CALL runtime·mstart(SB) 335 336 RET 337 338 // uint32 tstart_stdcall(M *newm); 339 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 340 MOVL newm+0(FP), BX 341 342 PUSHL BX 343 CALL runtime·tstart(SB) 344 POPL BX 345 346 // Adjust stack for stdcall to return properly. 347 MOVL (SP), AX // save return address 348 ADDL $4, SP // remove single parameter 349 MOVL AX, (SP) // restore return address 350 351 XORL AX, AX // return 0 == success 352 353 RET 354 355 // setldt(int entry, int address, int limit) 356 TEXT runtime·setldt(SB),NOSPLIT,$0 357 MOVL address+4(FP), CX 358 MOVL CX, 0x14(FS) 359 RET 360 361 // onosstack calls fn on OS stack. 362 // func onosstack(fn unsafe.Pointer, arg uint32) 363 TEXT runtime·onosstack(SB),NOSPLIT,$0 364 MOVL fn+0(FP), AX // to hide from 8l 365 MOVL arg+4(FP), BX 366 367 // Execute call on m->g0 stack, in case we are not actually 368 // calling a system call wrapper, like when running under WINE. 369 get_tls(CX) 370 CMPL CX, $0 371 JNE 3(PC) 372 // Not a Go-managed thread. Do not switch stack. 373 CALL AX 374 RET 375 376 MOVL g(CX), BP 377 MOVL g_m(BP), BP 378 379 // leave pc/sp for cpu profiler 380 MOVL (SP), SI 381 MOVL SI, m_libcallpc(BP) 382 MOVL g(CX), SI 383 MOVL SI, m_libcallg(BP) 384 // sp must be the last, because once async cpu profiler finds 385 // all three values to be non-zero, it will use them 386 LEAL usec+0(FP), SI 387 MOVL SI, m_libcallsp(BP) 388 389 MOVL m_g0(BP), SI 390 CMPL g(CX), SI 391 JNE switch 392 // executing on m->g0 already 393 CALL AX 394 JMP ret 395 396 switch: 397 // Switch to m->g0 stack and back. 398 MOVL (g_sched+gobuf_sp)(SI), SI 399 MOVL SP, -4(SI) 400 LEAL -4(SI), SP 401 CALL AX 402 MOVL 0(SP), SP 403 404 ret: 405 get_tls(CX) 406 MOVL g(CX), BP 407 MOVL g_m(BP), BP 408 MOVL $0, m_libcallsp(BP) 409 RET 410 411 // Runs on OS stack. duration (in 100ns units) is in BX. 412 TEXT runtime·usleep2(SB),NOSPLIT,$20 413 // Want negative 100ns units. 414 NEGL BX 415 MOVL $-1, hi-4(SP) 416 MOVL BX, lo-8(SP) 417 LEAL lo-8(SP), BX 418 MOVL BX, ptime-12(SP) 419 MOVL $0, alertable-16(SP) 420 MOVL $-1, handle-20(SP) 421 MOVL SP, BP 422 MOVL runtime·_NtWaitForSingleObject(SB), AX 423 CALL AX 424 MOVL BP, SP 425 RET 426 427 // Runs on OS stack. 428 TEXT runtime·switchtothread(SB),NOSPLIT,$0 429 MOVL SP, BP 430 MOVL runtime·_SwitchToThread(SB), AX 431 CALL AX 432 MOVL BP, SP 433 RET 434 435 // See http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/ 436 // Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2. 437 #define _INTERRUPT_TIME 0x7ffe0008 438 #define _SYSTEM_TIME 0x7ffe0014 439 #define time_lo 0 440 #define time_hi1 4 441 #define time_hi2 8 442 443 TEXT runtime·nanotime(SB),NOSPLIT,$0-8 444 CMPB runtime·useQPCTime(SB), $0 445 JNE useQPC 446 loop: 447 MOVL (_INTERRUPT_TIME+time_hi1), AX 448 MOVL (_INTERRUPT_TIME+time_lo), CX 449 MOVL (_INTERRUPT_TIME+time_hi2), DI 450 CMPL AX, DI 451 JNE loop 452 453 // wintime = DI:CX, multiply by 100 454 MOVL $100, AX 455 MULL CX 456 IMULL $100, DI 457 ADDL DI, DX 458 // wintime*100 = DX:AX, subtract startNano and return 459 SUBL runtime·startNano+0(SB), AX 460 SBBL runtime·startNano+4(SB), DX 461 MOVL AX, ret_lo+0(FP) 462 MOVL DX, ret_hi+4(FP) 463 RET 464 useQPC: 465 JMP runtime·nanotimeQPC(SB) 466 RET 467 468 TEXT time·now(SB),NOSPLIT,$0-20 469 CMPB runtime·useQPCTime(SB), $0 470 JNE useQPC 471 loop: 472 MOVL (_INTERRUPT_TIME+time_hi1), AX 473 MOVL (_INTERRUPT_TIME+time_lo), CX 474 MOVL (_INTERRUPT_TIME+time_hi2), DI 475 CMPL AX, DI 476 JNE loop 477 478 // w = DI:CX 479 // multiply by 100 480 MOVL $100, AX 481 MULL CX 482 IMULL $100, DI 483 ADDL DI, DX 484 // w*100 = DX:AX 485 // subtract startNano and save for return 486 SUBL runtime·startNano+0(SB), AX 487 SBBL runtime·startNano+4(SB), DX 488 MOVL AX, mono+12(FP) 489 MOVL DX, mono+16(FP) 490 491 wall: 492 MOVL (_SYSTEM_TIME+time_hi1), CX 493 MOVL (_SYSTEM_TIME+time_lo), AX 494 MOVL (_SYSTEM_TIME+time_hi2), DX 495 CMPL CX, DX 496 JNE wall 497 498 // w = DX:AX 499 // convert to Unix epoch (but still 100ns units) 500 #define delta 116444736000000000 501 SUBL $(delta & 0xFFFFFFFF), AX 502 SBBL $(delta >> 32), DX 503 504 // nano/100 = DX:AX 505 // split into two decimal halves by div 1e9. 506 // (decimal point is two spots over from correct place, 507 // but we avoid overflow in the high word.) 508 MOVL $1000000000, CX 509 DIVL CX 510 MOVL AX, DI 511 MOVL DX, SI 512 513 // DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9 514 // split DX into seconds and nanoseconds by div 1e7 magic multiply. 515 MOVL DX, AX 516 MOVL $1801439851, CX 517 MULL CX 518 SHRL $22, DX 519 MOVL DX, BX 520 IMULL $10000000, DX 521 MOVL SI, CX 522 SUBL DX, CX 523 524 // DI = sec/100 (still) 525 // BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100 526 // CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100 527 // store nsec for return 528 IMULL $100, CX 529 MOVL CX, nsec+8(FP) 530 531 // DI = sec/100 (still) 532 // BX = sec%100 533 // construct DX:AX = 64-bit sec and store for return 534 MOVL $0, DX 535 MOVL $100, AX 536 MULL DI 537 ADDL BX, AX 538 ADCL $0, DX 539 MOVL AX, sec+0(FP) 540 MOVL DX, sec+4(FP) 541 RET 542 useQPC: 543 JMP runtime·nowQPC(SB) 544 RET