diff options
Diffstat (limited to 'src/pkg/runtime/sys_windows_amd64.s')
-rw-r--r-- | src/pkg/runtime/sys_windows_amd64.s | 164 |
1 files changed, 75 insertions, 89 deletions
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s index c20a268b1..8c4caf867 100644 --- a/src/pkg/runtime/sys_windows_amd64.s +++ b/src/pkg/runtime/sys_windows_amd64.s @@ -3,13 +3,14 @@ // license that can be found in the LICENSE file. #include "zasm_GOOS_GOARCH.h" +#include "../../cmd/ld/textflag.h" // maxargs should be divisible by 2, as Windows stack // must be kept 16-byte aligned on syscall entry. #define maxargs 16 // void runtime·asmstdcall(void *c); -TEXT runtime·asmstdcall(SB),7,$0 +TEXT runtime·asmstdcall(SB),NOSPLIT,$0 // asmcgocall will put first argument into CX. PUSHQ CX // save for later MOVQ wincall_fn(CX), AX @@ -60,34 +61,7 @@ loadregs: RET -// This should be called on a system stack, -// so we don't need to concern about split stack. -TEXT runtime·badcallback(SB),7,$0 - SUBQ $48, SP - - // stderr - MOVQ $-12, CX // stderr - MOVQ CX, 0(SP) - MOVQ runtime·GetStdHandle(SB), AX - CALL AX - - MOVQ AX, CX // handle - MOVQ CX, 0(SP) - MOVQ $runtime·badcallbackmsg(SB), DX // pointer - MOVQ DX, 8(SP) - MOVL $runtime·badcallbacklen(SB), R8 // count - MOVQ R8, 16(SP) - LEAQ 40(SP), R9 // written count - MOVQ $0, 0(R9) - MOVQ R9, 24(SP) - MOVQ $0, 32(SP) // overlapped - MOVQ runtime·WriteFile(SB), AX - CALL AX - - ADDQ $48, SP - RET - -TEXT runtime·badsignal(SB),7,$48 +TEXT runtime·badsignal2(SB),NOSPLIT,$48 // stderr MOVQ $-12, CX // stderr MOVQ CX, 0(SP) @@ -110,18 +84,18 @@ TEXT runtime·badsignal(SB),7,$48 RET // faster get/set last error -TEXT runtime·getlasterror(SB),7,$0 +TEXT runtime·getlasterror(SB),NOSPLIT,$0 MOVQ 0x30(GS), AX MOVL 0x68(AX), AX RET -TEXT runtime·setlasterror(SB),7,$0 +TEXT runtime·setlasterror(SB),NOSPLIT,$0 MOVL err+0(FP), AX MOVQ 0x30(GS), CX MOVL AX, 0x68(CX) RET -TEXT runtime·sigtramp(SB),7,$0 +TEXT runtime·sigtramp(SB),NOSPLIT,$0 // CX: exception record // R8: context @@ -145,7 +119,7 @@ TEXT runtime·sigtramp(SB),7,$0 MOVQ m(CX), AX CMPQ AX, $0 JNE 2(PC) - CALL runtime·badsignal(SB) + CALL runtime·badsignal2(SB) MOVQ g(CX), CX MOVQ CX, 16(SP) @@ -166,20 +140,20 @@ TEXT runtime·sigtramp(SB),7,$0 sigdone: RET -TEXT runtime·ctrlhandler(SB),7,$8 +TEXT runtime·ctrlhandler(SB),NOSPLIT,$8 MOVQ CX, 16(SP) // spill MOVQ $runtime·ctrlhandler1(SB), CX MOVQ CX, 0(SP) CALL runtime·externalthreadhandler(SB) RET -TEXT runtime·profileloop(SB),7,$8 +TEXT runtime·profileloop(SB),NOSPLIT,$8 MOVQ $runtime·profileloop1(SB), CX MOVQ CX, 0(SP) CALL runtime·externalthreadhandler(SB) RET -TEXT runtime·externalthreadhandler(SB),7,$0 +TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP PUSHQ BX @@ -223,32 +197,37 @@ TEXT runtime·externalthreadhandler(SB),7,$0 POPQ BP RET -// Continuation of thunk function created for each callback by ../thread.c compilecallback, -// runs on Windows stack (not Go stack). -// Thunk code designed to have minimal size for it is copied many (up to thousands) times. -// -// thunk: -// MOVQ $fn, AX -// PUSHQ AX -// MOVQ $argsize, AX -// PUSHQ AX -// MOVQ $runtime·callbackasm, AX -// JMP AX -TEXT runtime·callbackasm(SB),7,$0 +GLOBL runtime·cbctxts(SB), $8 + +TEXT runtime·callbackasm1(SB),NOSPLIT,$0 // Construct args vector for cgocallback(). // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 // args from the 5th on are on the stack. // In any case, even if function has 0,1,2,3,4 args, there is reserved // but uninitialized "shadow space" for the first 4 args. // The values are in registers. - MOVQ CX, (24+0)(SP) - MOVQ DX, (24+8)(SP) - MOVQ R8, (24+16)(SP) - MOVQ R9, (24+24)(SP) - // 6l does not accept writing POPQs here issuing a warning "unbalanced PUSH/POP" - MOVQ 0(SP), DX // POPQ DX - MOVQ 8(SP), AX // POPQ AX - ADDQ $16, SP + MOVQ CX, (16+0)(SP) + MOVQ DX, (16+8)(SP) + MOVQ R8, (16+16)(SP) + MOVQ R9, (16+24)(SP) + + // remove return address from stack, we are not returning there + MOVQ 0(SP), AX + ADDQ $8, SP + + // determine index into runtime·cbctxts table + SUBQ $runtime·callbackasm(SB), AX + MOVQ $0, DX + MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long + DIVL CX, + + // find correspondent runtime·cbctxts table entry + MOVQ runtime·cbctxts(SB), CX + MOVQ -8(CX)(AX*8), AX + + // extract callback context + MOVQ cbctxt_argsize(AX), DX + MOVQ cbctxt_gobody(AX), AX // preserve whatever's at the memory location that // the callback will use to store the return value @@ -258,8 +237,6 @@ TEXT runtime·callbackasm(SB),7,$0 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved // as required by windows callback convention. - // 6l does not allow writing many PUSHQs here issuing a warning "nosplit stack overflow" - // the warning has no sense as this code uses os thread stack PUSHFQ SUBQ $64, SP MOVQ DI, 56(SP) @@ -274,18 +251,17 @@ TEXT runtime·callbackasm(SB),7,$0 // prepare call stack. use SUBQ to hide from stack frame checks // cgocallback(Go func, void *frame, uintptr framesize) SUBQ $24, SP - MOVQ DX, 16(SP) // uintptr framesize - MOVQ CX, 8(SP) // void *frame - MOVQ AX, 0(SP) // Go func + MOVQ DX, 16(SP) // argsize (including return value) + MOVQ CX, 8(SP) // callback parameters + MOVQ AX, 0(SP) // address of target Go function CLD - CALL runtime·cgocallback_gofunc(SB) + CALL runtime·cgocallback_gofunc(SB) MOVQ 0(SP), AX MOVQ 8(SP), CX MOVQ 16(SP), DX ADDQ $24, SP // restore registers as required for windows callback - // 6l does not allow writing many POPs here issuing a warning "nosplit stack overflow" MOVQ 0(SP), R15 MOVQ 8(SP), R14 MOVQ 16(SP), R13 @@ -301,7 +277,7 @@ TEXT runtime·callbackasm(SB),7,$0 POPQ -8(CX)(DX*1) // restore bytes just after the args RET -TEXT runtime·setstacklimits(SB),7,$0 +TEXT runtime·setstacklimits(SB),NOSPLIT,$0 MOVQ 0x30(GS), CX MOVQ $0, 0x10(CX) MOVQ $0xffffffffffff, AX @@ -309,7 +285,7 @@ TEXT runtime·setstacklimits(SB),7,$0 RET // uint32 tstart_stdcall(M *newm); -TEXT runtime·tstart_stdcall(SB),7,$0 +TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 // CX contains first arg newm MOVQ m_g0(CX), DX // g @@ -335,46 +311,56 @@ TEXT runtime·tstart_stdcall(SB),7,$0 RET // set tls base to DI -TEXT runtime·settls(SB),7,$0 +TEXT runtime·settls(SB),NOSPLIT,$0 MOVQ DI, 0x28(GS) RET // void install_exception_handler() -TEXT runtime·install_exception_handler(SB),7,$0 +TEXT runtime·install_exception_handler(SB),NOSPLIT,$0 CALL runtime·setstacklimits(SB) RET -TEXT runtime·remove_exception_handler(SB),7,$0 +TEXT runtime·remove_exception_handler(SB),NOSPLIT,$0 RET -TEXT runtime·osyield(SB),7,$8 - // Tried NtYieldExecution but it doesn't yield hard enough. - // NtWaitForSingleObject being used here as Sleep(0). - // The CALL is safe because NtXxx is a system call wrapper: - // it puts the right system call number in AX, then does - // a SYSENTER and a RET. - MOVQ runtime·NtWaitForSingleObject(SB), AX - MOVQ $1, BX - NEGQ BX - MOVQ SP, R8 // ptime - MOVQ BX, (R8) - MOVQ $-1, CX // handle - MOVQ $0, DX // alertable +// Sleep duration is in 100ns units. +TEXT runtime·usleep1(SB),NOSPLIT,$0 + MOVL duration+0(FP), BX + MOVQ $runtime·usleep2(SB), AX // to hide from 6l + + // Execute call on m->g0 stack, in case we are not actually + // calling a system call wrapper, like when running under WINE. + get_tls(R15) + CMPQ R15, $0 + JNE 3(PC) + // Not a Go-managed thread. Do not switch stack. CALL AX RET -TEXT runtime·usleep(SB),7,$8 - // The CALL is safe because NtXxx is a system call wrapper: - // it puts the right system call number in AX, then does - // a SYSENTER and a RET. - MOVQ runtime·NtWaitForSingleObject(SB), AX - // Have 1us units; want negative 100ns units. - MOVL usec+0(FP), BX - IMULQ $10, BX + MOVQ m(R15), R14 + MOVQ m_g0(R14), R14 + CMPQ g(R15), R14 + JNE 3(PC) + // executing on m->g0 already + CALL AX + RET + + // Switch to m->g0 stack and back. + MOVQ (g_sched+gobuf_sp)(R14), R14 + MOVQ SP, -8(R14) + LEAQ -8(R14), SP + CALL AX + MOVQ 0(SP), SP + RET + +// Runs on OS stack. duration (in 100ns units) is in BX. +TEXT runtime·usleep2(SB),NOSPLIT,$8 + // Want negative 100ns units. NEGQ BX MOVQ SP, R8 // ptime MOVQ BX, (R8) MOVQ $-1, CX // handle MOVQ $0, DX // alertable + MOVQ runtime·NtWaitForSingleObject(SB), AX CALL AX RET |