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