github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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 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 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 sigtramp<>(SB) 167 168 // Called by OS using stdcall ABI: bool ctrlhandler(uint32). 169 TEXT runtime·ctrlhandler(SB),NOSPLIT,$0 170 PUSHL $runtime·ctrlhandler1(SB) 171 NOP SP // tell vet SP changed - stop checking offsets 172 CALL runtime·externalthreadhandler(SB) 173 MOVL 4(SP), CX 174 ADDL $12, SP 175 JMP CX 176 177 // Called by OS using stdcall ABI: uint32 profileloop(void*). 178 TEXT runtime·profileloop(SB),NOSPLIT,$0 179 PUSHL $runtime·profileloop1(SB) 180 NOP SP // tell vet SP changed - stop checking offsets 181 CALL runtime·externalthreadhandler(SB) 182 MOVL 4(SP), CX 183 ADDL $12, SP 184 JMP CX 185 186 TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 187 PUSHL BP 188 MOVL SP, BP 189 PUSHL BX 190 PUSHL SI 191 PUSHL DI 192 PUSHL 0x14(FS) 193 MOVL SP, DX 194 195 // setup dummy m, g 196 SUBL $m__size, SP // space for M 197 MOVL SP, 0(SP) 198 MOVL $m__size, 4(SP) 199 CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX 200 201 LEAL m_tls(SP), CX 202 MOVL CX, 0x14(FS) 203 MOVL SP, BX 204 SUBL $g__size, SP // space for G 205 MOVL SP, g(CX) 206 MOVL SP, m_g0(BX) 207 208 MOVL SP, 0(SP) 209 MOVL $g__size, 4(SP) 210 CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX 211 LEAL g__size(SP), BX 212 MOVL BX, g_m(SP) 213 214 LEAL -32768(SP), CX // must be less than SizeOfStackReserve set by linker 215 MOVL CX, (g_stack+stack_lo)(SP) 216 ADDL $const__StackGuard, CX 217 MOVL CX, g_stackguard0(SP) 218 MOVL CX, g_stackguard1(SP) 219 MOVL DX, (g_stack+stack_hi)(SP) 220 221 PUSHL AX // room for return value 222 PUSHL 16(BP) // arg for handler 223 CALL 8(BP) 224 POPL CX 225 POPL AX // pass return value to Windows in AX 226 227 get_tls(CX) 228 MOVL g(CX), CX 229 MOVL (g_stack+stack_hi)(CX), SP 230 POPL 0x14(FS) 231 POPL DI 232 POPL SI 233 POPL BX 234 POPL BP 235 RET 236 237 GLOBL runtime·cbctxts(SB), NOPTR, $4 238 239 TEXT runtime·callbackasm1(SB),NOSPLIT,$0 240 MOVL 0(SP), AX // will use to find our callback context 241 242 // remove return address from stack, we are not returning to callbackasm, but to its caller. 243 ADDL $4, SP 244 245 // address to callback parameters into CX 246 LEAL 4(SP), CX 247 248 // save registers as required for windows callback 249 PUSHL DI 250 PUSHL SI 251 PUSHL BP 252 PUSHL BX 253 254 // Go ABI requires DF flag to be cleared. 255 CLD 256 257 // determine index into runtime·cbs table 258 SUBL $runtime·callbackasm(SB), AX 259 MOVL $0, DX 260 MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 261 DIVL BX 262 SUBL $1, AX // subtract 1 because return PC is to the next slot 263 264 // Create a struct callbackArgs on our stack. 265 SUBL $(12+callbackArgs__size), SP 266 MOVL AX, (12+callbackArgs_index)(SP) // callback index 267 MOVL CX, (12+callbackArgs_args)(SP) // address of args vector 268 MOVL $0, (12+callbackArgs_result)(SP) // result 269 LEAL 12(SP), AX // AX = &callbackArgs{...} 270 271 // Call cgocallback, which will call callbackWrap(frame). 272 MOVL $0, 8(SP) // context 273 MOVL AX, 4(SP) // frame (address of callbackArgs) 274 LEAL ·callbackWrap(SB), AX 275 MOVL AX, 0(SP) // PC of function to call 276 CALL runtime·cgocallback(SB) 277 278 // Get callback result. 279 MOVL (12+callbackArgs_result)(SP), AX 280 // Get popRet. 281 MOVL (12+callbackArgs_retPop)(SP), CX // Can't use a callee-save register 282 ADDL $(12+callbackArgs__size), SP 283 284 // restore registers as required for windows callback 285 POPL BX 286 POPL BP 287 POPL SI 288 POPL DI 289 290 // remove callback parameters before return (as per Windows spec) 291 POPL DX 292 ADDL CX, SP 293 PUSHL DX 294 295 CLD 296 297 RET 298 299 // void tstart(M *newm); 300 TEXT tstart<>(SB),NOSPLIT,$0 301 MOVL newm+0(FP), CX // m 302 MOVL m_g0(CX), DX // g 303 304 // Layout new m scheduler stack on os stack. 305 MOVL SP, AX 306 MOVL AX, (g_stack+stack_hi)(DX) 307 SUBL $(64*1024), AX // initial stack size (adjusted later) 308 MOVL AX, (g_stack+stack_lo)(DX) 309 ADDL $const__StackGuard, AX 310 MOVL AX, g_stackguard0(DX) 311 MOVL AX, g_stackguard1(DX) 312 313 // Set up tls. 314 LEAL m_tls(CX), SI 315 MOVL SI, 0x14(FS) 316 MOVL CX, g_m(DX) 317 MOVL DX, g(SI) 318 319 // Someday the convention will be D is always cleared. 320 CLD 321 322 CALL runtime·stackcheck(SB) // clobbers AX,CX 323 CALL runtime·mstart(SB) 324 325 RET 326 327 // uint32 tstart_stdcall(M *newm); 328 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 329 MOVL newm+0(FP), BX 330 331 PUSHL BX 332 CALL tstart<>(SB) 333 POPL BX 334 335 // Adjust stack for stdcall to return properly. 336 MOVL (SP), AX // save return address 337 ADDL $4, SP // remove single parameter 338 MOVL AX, (SP) // restore return address 339 340 XORL AX, AX // return 0 == success 341 342 RET 343 344 // setldt(int entry, int address, int limit) 345 TEXT runtime·setldt(SB),NOSPLIT,$0 346 MOVL base+4(FP), CX 347 MOVL CX, 0x14(FS) 348 RET 349 350 // onosstack calls fn on OS stack. 351 // func onosstack(fn unsafe.Pointer, arg uint32) 352 TEXT runtime·onosstack(SB),NOSPLIT,$0 353 MOVL fn+0(FP), AX // to hide from 8l 354 MOVL arg+4(FP), BX 355 356 // Execute call on m->g0 stack, in case we are not actually 357 // calling a system call wrapper, like when running under WINE. 358 get_tls(CX) 359 CMPL CX, $0 360 JNE 3(PC) 361 // Not a Go-managed thread. Do not switch stack. 362 CALL AX 363 RET 364 365 MOVL g(CX), BP 366 MOVL g_m(BP), BP 367 368 // leave pc/sp for cpu profiler 369 MOVL (SP), SI 370 MOVL SI, m_libcallpc(BP) 371 MOVL g(CX), SI 372 MOVL SI, m_libcallg(BP) 373 // sp must be the last, because once async cpu profiler finds 374 // all three values to be non-zero, it will use them 375 LEAL fn+0(FP), SI 376 MOVL SI, m_libcallsp(BP) 377 378 MOVL m_g0(BP), SI 379 CMPL g(CX), SI 380 JNE switch 381 // executing on m->g0 already 382 CALL AX 383 JMP ret 384 385 switch: 386 // Switch to m->g0 stack and back. 387 MOVL (g_sched+gobuf_sp)(SI), SI 388 MOVL SP, -4(SI) 389 LEAL -4(SI), SP 390 CALL AX 391 MOVL 0(SP), SP 392 393 ret: 394 get_tls(CX) 395 MOVL g(CX), BP 396 MOVL g_m(BP), BP 397 MOVL $0, m_libcallsp(BP) 398 RET 399 400 // Runs on OS stack. duration (in 100ns units) is in BX. 401 TEXT runtime·usleep2(SB),NOSPLIT,$20 402 // Want negative 100ns units. 403 NEGL BX 404 MOVL $-1, hi-4(SP) 405 MOVL BX, lo-8(SP) 406 LEAL lo-8(SP), BX 407 MOVL BX, ptime-12(SP) 408 MOVL $0, alertable-16(SP) 409 MOVL $-1, handle-20(SP) 410 MOVL SP, BP 411 MOVL runtime·_NtWaitForSingleObject(SB), AX 412 CALL AX 413 MOVL BP, SP 414 RET 415 416 // Runs on OS stack. duration (in 100ns units) is in BX. 417 TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36 418 get_tls(CX) 419 CMPL CX, $0 420 JE gisnotset 421 422 // Want negative 100ns units. 423 NEGL BX 424 MOVL $-1, hi-4(SP) 425 MOVL BX, lo-8(SP) 426 427 MOVL g(CX), CX 428 MOVL g_m(CX), CX 429 MOVL (m_mOS+mOS_highResTimer)(CX), CX 430 MOVL CX, saved_timer-12(SP) 431 432 MOVL $0, fResume-16(SP) 433 MOVL $0, lpArgToCompletionRoutine-20(SP) 434 MOVL $0, pfnCompletionRoutine-24(SP) 435 MOVL $0, lPeriod-28(SP) 436 LEAL lo-8(SP), BX 437 MOVL BX, lpDueTime-32(SP) 438 MOVL CX, hTimer-36(SP) 439 MOVL SP, BP 440 MOVL runtime·_SetWaitableTimer(SB), AX 441 CALL AX 442 MOVL BP, SP 443 444 MOVL $0, ptime-28(SP) 445 MOVL $0, alertable-32(SP) 446 MOVL saved_timer-12(SP), CX 447 MOVL CX, handle-36(SP) 448 MOVL SP, BP 449 MOVL runtime·_NtWaitForSingleObject(SB), AX 450 CALL AX 451 MOVL BP, SP 452 453 RET 454 455 gisnotset: 456 // TLS is not configured. Call usleep2 instead. 457 MOVL $runtime·usleep2(SB), AX 458 CALL AX 459 RET 460 461 // Runs on OS stack. 462 TEXT runtime·switchtothread(SB),NOSPLIT,$0 463 MOVL SP, BP 464 MOVL runtime·_SwitchToThread(SB), AX 465 CALL AX 466 MOVL BP, SP 467 RET 468 469 // See https://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/ 470 // Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2. 471 #define _INTERRUPT_TIME 0x7ffe0008 472 #define _SYSTEM_TIME 0x7ffe0014 473 #define time_lo 0 474 #define time_hi1 4 475 #define time_hi2 8 476 477 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 478 CMPB runtime·useQPCTime(SB), $0 479 JNE useQPC 480 loop: 481 MOVL (_INTERRUPT_TIME+time_hi1), AX 482 MOVL (_INTERRUPT_TIME+time_lo), CX 483 MOVL (_INTERRUPT_TIME+time_hi2), DI 484 CMPL AX, DI 485 JNE loop 486 487 // wintime = DI:CX, multiply by 100 488 MOVL $100, AX 489 MULL CX 490 IMULL $100, DI 491 ADDL DI, DX 492 // wintime*100 = DX:AX 493 MOVL AX, ret_lo+0(FP) 494 MOVL DX, ret_hi+4(FP) 495 RET 496 useQPC: 497 JMP runtime·nanotimeQPC(SB) 498 RET 499 500 TEXT time·now(SB),NOSPLIT,$0-20 501 CMPB runtime·useQPCTime(SB), $0 502 JNE useQPC 503 loop: 504 MOVL (_INTERRUPT_TIME+time_hi1), AX 505 MOVL (_INTERRUPT_TIME+time_lo), CX 506 MOVL (_INTERRUPT_TIME+time_hi2), DI 507 CMPL AX, DI 508 JNE loop 509 510 // w = DI:CX 511 // multiply by 100 512 MOVL $100, AX 513 MULL CX 514 IMULL $100, DI 515 ADDL DI, DX 516 // w*100 = DX:AX 517 MOVL AX, mono+12(FP) 518 MOVL DX, mono+16(FP) 519 520 wall: 521 MOVL (_SYSTEM_TIME+time_hi1), CX 522 MOVL (_SYSTEM_TIME+time_lo), AX 523 MOVL (_SYSTEM_TIME+time_hi2), DX 524 CMPL CX, DX 525 JNE wall 526 527 // w = DX:AX 528 // convert to Unix epoch (but still 100ns units) 529 #define delta 116444736000000000 530 SUBL $(delta & 0xFFFFFFFF), AX 531 SBBL $(delta >> 32), DX 532 533 // nano/100 = DX:AX 534 // split into two decimal halves by div 1e9. 535 // (decimal point is two spots over from correct place, 536 // but we avoid overflow in the high word.) 537 MOVL $1000000000, CX 538 DIVL CX 539 MOVL AX, DI 540 MOVL DX, SI 541 542 // DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9 543 // split DX into seconds and nanoseconds by div 1e7 magic multiply. 544 MOVL DX, AX 545 MOVL $1801439851, CX 546 MULL CX 547 SHRL $22, DX 548 MOVL DX, BX 549 IMULL $10000000, DX 550 MOVL SI, CX 551 SUBL DX, CX 552 553 // DI = sec/100 (still) 554 // BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100 555 // CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100 556 // store nsec for return 557 IMULL $100, CX 558 MOVL CX, nsec+8(FP) 559 560 // DI = sec/100 (still) 561 // BX = sec%100 562 // construct DX:AX = 64-bit sec and store for return 563 MOVL $0, DX 564 MOVL $100, AX 565 MULL DI 566 ADDL BX, AX 567 ADCL $0, DX 568 MOVL AX, sec+0(FP) 569 MOVL DX, sec+4(FP) 570 RET 571 useQPC: 572 JMP runtime·nowQPC(SB) 573 RET