github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/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 "go_asm.h"
     6  #include "go_tls.h"
     7  #include "textflag.h"
     8  
     9  // maxargs should be divisible by 2, as Windows stack
    10  // must be kept 16-byte aligned on syscall entry.
    11  #define maxargs 16
    12  
    13  // void runtime·asmstdcall(void *c);
    14  TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
    15  	// asmcgocall will put first argument into CX.
    16  	PUSHQ	CX			// save for later
    17  	MOVQ	libcall_fn(CX), AX
    18  	MOVQ	libcall_args(CX), SI
    19  	MOVQ	libcall_n(CX), CX
    20  
    21  	// SetLastError(0).
    22  	MOVQ	0x30(GS), DI
    23  	MOVL	$0, 0x68(DI)
    24  
    25  	SUBQ	$(maxargs*8), SP	// room for args
    26  
    27  	// Fast version, do not store args on the stack.
    28  	CMPL	CX, $4
    29  	JLE	loadregs
    30  
    31  	// Check we have enough room for args.
    32  	CMPL	CX, $maxargs
    33  	JLE	2(PC)
    34  	INT	$3			// not enough room -> crash
    35  
    36  	// Copy args to the stack.
    37  	MOVQ	SP, DI
    38  	CLD
    39  	REP; MOVSQ
    40  	MOVQ	SP, SI
    41  
    42  loadregs:
    43  	// Load first 4 args into correspondent registers.
    44  	MOVQ	0(SI), CX
    45  	MOVQ	8(SI), DX
    46  	MOVQ	16(SI), R8
    47  	MOVQ	24(SI), R9
    48  
    49  	// Call stdcall function.
    50  	CALL	AX
    51  
    52  	ADDQ	$(maxargs*8), SP
    53  
    54  	// Return result.
    55  	POPQ	CX
    56  	MOVQ	AX, libcall_r1(CX)
    57  
    58  	// GetLastError().
    59  	MOVQ	0x30(GS), DI
    60  	MOVL	0x68(DI), AX
    61  	MOVQ	AX, libcall_err(CX)
    62  
    63  	RET
    64  
    65  TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48
    66  	// stderr
    67  	MOVQ	$-12, CX // stderr
    68  	MOVQ	CX, 0(SP)
    69  	MOVQ	runtime·_GetStdHandle(SB), AX
    70  	CALL	AX
    71  
    72  	MOVQ	AX, CX	// handle
    73  	MOVQ	CX, 0(SP)
    74  	MOVQ	$runtime·badsignalmsg(SB), DX // pointer
    75  	MOVQ	DX, 8(SP)
    76  	MOVL	$runtime·badsignallen(SB), R8 // count
    77  	MOVQ	R8, 16(SP)
    78  	LEAQ	40(SP), R9  // written count
    79  	MOVQ	$0, 0(R9)
    80  	MOVQ	R9, 24(SP)
    81  	MOVQ	$0, 32(SP)	// overlapped
    82  	MOVQ	runtime·_WriteFile(SB), AX
    83  	CALL	AX
    84  	
    85  	RET
    86  
    87  // faster get/set last error
    88  TEXT runtime·getlasterror(SB),NOSPLIT,$0
    89  	MOVQ	0x30(GS), AX
    90  	MOVL	0x68(AX), AX
    91  	MOVL	AX, ret+0(FP)
    92  	RET
    93  
    94  TEXT runtime·setlasterror(SB),NOSPLIT,$0
    95  	MOVL	err+0(FP), AX
    96  	MOVQ	0x30(GS),	CX
    97  	MOVL	AX, 0x68(CX)
    98  	RET
    99  
   100  // Called by Windows as a Vectored Exception Handler (VEH).
   101  // First argument is pointer to struct containing
   102  // exception record and context pointers.
   103  // Handler function is stored in AX.
   104  // Return 0 for 'not handled', -1 for handled.
   105  TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0-0
   106  	// CX: PEXCEPTION_POINTERS ExceptionInfo
   107  
   108  	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
   109  	// as required by windows callback convention.
   110  	PUSHFQ
   111  	SUBQ	$112, SP
   112  	MOVQ	DI, 80(SP)
   113  	MOVQ	SI, 72(SP)
   114  	MOVQ	BP, 64(SP)
   115  	MOVQ	BX, 56(SP)
   116  	MOVQ	R12, 48(SP)
   117  	MOVQ	R13, 40(SP)
   118  	MOVQ	R14, 32(SP)
   119  	MOVQ	R15, 88(SP)
   120  
   121  	MOVQ	AX, R15	// save handler address
   122  
   123  	// find g
   124  	get_tls(DX)
   125  	CMPQ	DX, $0
   126  	JNE	3(PC)
   127  	MOVQ	$0, AX // continue
   128  	JMP	done
   129  	MOVQ	g(DX), DX
   130  	CMPQ	DX, $0
   131  	JNE	2(PC)
   132  	CALL	runtime·badsignal2(SB)
   133  
   134  	// save g and SP in case of stack switch
   135  	MOVQ	DX, 96(SP) // g
   136  	MOVQ	SP, 104(SP)
   137  
   138  	// do we need to switch to the g0 stack?
   139  	MOVQ	g_m(DX), BX
   140  	MOVQ	m_g0(BX), BX
   141  	CMPQ	DX, BX
   142  	JEQ	g0
   143  
   144  	// switch to g0 stack
   145  	get_tls(BP)
   146  	MOVQ	BX, g(BP)
   147  	MOVQ	(g_sched+gobuf_sp)(BX), DI
   148  	// make it look like mstart called us on g0, to stop traceback
   149  	SUBQ	$8, DI
   150  	MOVQ	$runtime·mstart(SB), SI
   151  	MOVQ	SI, 0(DI)
   152  	// traceback will think that we've done PUSHFQ and SUBQ
   153  	// on this stack, so subtract them here to match.
   154  	// (we need room for sighandler arguments anyway).
   155  	// and re-save old SP for restoring later.
   156  	SUBQ	$(112+8), DI
   157  	// save g, save old stack pointer.
   158  	MOVQ	SP, 104(DI)
   159  	MOVQ	DI, SP
   160  
   161  g0:
   162  	MOVQ	0(CX), BX // ExceptionRecord*
   163  	MOVQ	8(CX), CX // Context*
   164  	MOVQ	BX, 0(SP)
   165  	MOVQ	CX, 8(SP)
   166  	MOVQ	DX, 16(SP)
   167  	CALL	R15	// call handler
   168  	// AX is set to report result back to Windows
   169  	MOVL	24(SP), AX
   170  
   171  	// switch back to original stack and g
   172  	// no-op if we never left.
   173  	MOVQ	104(SP), SP
   174  	MOVQ	96(SP), DX
   175  	get_tls(BP)
   176  	MOVQ	DX, g(BP)
   177  
   178  done:
   179  	// restore registers as required for windows callback
   180  	MOVQ	88(SP), R15
   181  	MOVQ	32(SP), R14
   182  	MOVQ	40(SP), R13
   183  	MOVQ	48(SP), R12
   184  	MOVQ	56(SP), BX
   185  	MOVQ	64(SP), BP
   186  	MOVQ	72(SP), SI
   187  	MOVQ	80(SP), DI
   188  	ADDQ	$112, SP
   189  	POPFQ
   190  
   191  	RET
   192  
   193  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   194  	MOVQ	$runtime·exceptionhandler(SB), AX
   195  	JMP	runtime·sigtramp(SB)
   196  
   197  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   198  	MOVQ	$runtime·firstcontinuehandler(SB), AX
   199  	JMP	runtime·sigtramp(SB)
   200  
   201  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   202  	MOVQ	$runtime·lastcontinuehandler(SB), AX
   203  	JMP	runtime·sigtramp(SB)
   204  
   205  TEXT runtime·ctrlhandler(SB),NOSPLIT|NOFRAME,$8
   206  	MOVQ	CX, 16(SP)		// spill
   207  	MOVQ	$runtime·ctrlhandler1(SB), CX
   208  	MOVQ	CX, 0(SP)
   209  	CALL	runtime·externalthreadhandler(SB)
   210  	RET
   211  
   212  TEXT runtime·profileloop(SB),NOSPLIT|NOFRAME,$8
   213  	MOVQ	$runtime·profileloop1(SB), CX
   214  	MOVQ	CX, 0(SP)
   215  	CALL	runtime·externalthreadhandler(SB)
   216  	RET
   217  
   218  TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
   219  	PUSHQ	BP
   220  	MOVQ	SP, BP
   221  	PUSHQ	BX
   222  	PUSHQ	SI
   223  	PUSHQ	DI
   224  	PUSHQ	0x28(GS)
   225  	MOVQ	SP, DX
   226  
   227  	// setup dummy m, g
   228  	SUBQ	$m__size, SP		// space for M
   229  	MOVQ	SP, 0(SP)
   230  	MOVQ	$m__size, 8(SP)
   231  	CALL	runtime·memclr(SB)	// smashes AX,BX,CX, maybe BP
   232  
   233  	LEAQ	m_tls(SP), CX
   234  	MOVQ	CX, 0x28(GS)
   235  	MOVQ	SP, BX
   236  	SUBQ	$g__size, SP		// space for G
   237  	MOVQ	SP, g(CX)
   238  	MOVQ	SP, m_g0(BX)
   239  
   240  	MOVQ	SP, 0(SP)
   241  	MOVQ	$g__size, 8(SP)
   242  	CALL	runtime·memclr(SB)	// smashes AX,BX,CX, maybe BP
   243  	LEAQ	g__size(SP), BX
   244  	MOVQ	BX, g_m(SP)
   245  
   246  	LEAQ	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
   247  	MOVQ	CX, (g_stack+stack_lo)(SP)
   248  	ADDQ	$const__StackGuard, CX
   249  	MOVQ	CX, g_stackguard0(SP)
   250  	MOVQ	CX, g_stackguard1(SP)
   251  	MOVQ	DX, (g_stack+stack_hi)(SP)
   252  
   253  	PUSHQ	AX			// room for return value
   254  	PUSHQ	32(BP)			// arg for handler
   255  	CALL	16(BP)
   256  	POPQ	CX
   257  	POPQ	AX			// pass return value to Windows in AX
   258  
   259  	get_tls(CX)
   260  	MOVQ	g(CX), CX
   261  	MOVQ	(g_stack+stack_hi)(CX), SP
   262  	POPQ	0x28(GS)
   263  	POPQ	DI
   264  	POPQ	SI
   265  	POPQ	BX
   266  	POPQ	BP
   267  	RET
   268  
   269  GLOBL runtime·cbctxts(SB), NOPTR, $8
   270  
   271  TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   272  	// Construct args vector for cgocallback().
   273  	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   274  	// args from the 5th on are on the stack.
   275  	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   276  	// but uninitialized "shadow space" for the first 4 args.
   277  	// The values are in registers.
   278    	MOVQ	CX, (16+0)(SP)
   279    	MOVQ	DX, (16+8)(SP)
   280    	MOVQ	R8, (16+16)(SP)
   281    	MOVQ	R9, (16+24)(SP)
   282  
   283  	// remove return address from stack, we are not returning there
   284    	MOVQ	0(SP), AX
   285  	ADDQ	$8, SP
   286  
   287  	// determine index into runtime·cbctxts table
   288  	MOVQ	$runtime·callbackasm(SB), DX
   289  	SUBQ	DX, AX
   290  	MOVQ	$0, DX
   291  	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   292  	DIVL	CX
   293  
   294  	// find correspondent runtime·cbctxts table entry
   295  	MOVQ	runtime·cbctxts(SB), CX
   296  	MOVQ	-8(CX)(AX*8), AX
   297  
   298  	// extract callback context
   299  	MOVQ	wincallbackcontext_argsize(AX), DX
   300  	MOVQ	wincallbackcontext_gobody(AX), AX
   301  
   302  	// preserve whatever's at the memory location that
   303  	// the callback will use to store the return value
   304  	LEAQ	8(SP), CX       // args vector, skip return address
   305  	PUSHQ	0(CX)(DX*1)     // store 8 bytes from just after the args array
   306  	ADDQ	$8, DX          // extend argsize by size of return value
   307  
   308  	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
   309  	// as required by windows callback convention.
   310  	PUSHFQ
   311  	SUBQ	$64, SP
   312  	MOVQ	DI, 56(SP)
   313  	MOVQ	SI, 48(SP)
   314  	MOVQ	BP, 40(SP)
   315  	MOVQ	BX, 32(SP)
   316  	MOVQ	R12, 24(SP)
   317  	MOVQ	R13, 16(SP)
   318  	MOVQ	R14, 8(SP)
   319  	MOVQ	R15, 0(SP)
   320  
   321  	// prepare call stack.  use SUBQ to hide from stack frame checks
   322  	// cgocallback(Go func, void *frame, uintptr framesize)
   323  	SUBQ	$24, SP
   324  	MOVQ	DX, 16(SP)	// argsize (including return value)
   325  	MOVQ	CX, 8(SP)	// callback parameters
   326  	MOVQ	AX, 0(SP)	// address of target Go function
   327  	CLD
   328  	CALL	runtime·cgocallback_gofunc(SB)
   329  	MOVQ	0(SP), AX
   330  	MOVQ	8(SP), CX
   331  	MOVQ	16(SP), DX
   332  	ADDQ	$24, SP
   333  
   334  	// restore registers as required for windows callback
   335  	MOVQ	0(SP), R15
   336  	MOVQ	8(SP), R14
   337  	MOVQ	16(SP), R13
   338  	MOVQ	24(SP), R12
   339  	MOVQ	32(SP), BX
   340  	MOVQ	40(SP), BP
   341  	MOVQ	48(SP), SI
   342  	MOVQ	56(SP), DI
   343  	ADDQ	$64, SP
   344  	POPFQ
   345  
   346  	MOVL	-8(CX)(DX*1), AX  // return value
   347  	POPQ	-8(CX)(DX*1)      // restore bytes just after the args
   348  	RET
   349  
   350  // uint32 tstart_stdcall(M *newm);
   351  TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   352  	// CX contains first arg newm
   353  	MOVQ	m_g0(CX), DX		// g
   354  
   355  	// Layout new m scheduler stack on os stack.
   356  	MOVQ	SP, AX
   357  	MOVQ	AX, (g_stack+stack_hi)(DX)
   358  	SUBQ	$(64*1024), AX		// stack size
   359  	MOVQ	AX, (g_stack+stack_lo)(DX)
   360  	ADDQ	$const__StackGuard, AX
   361  	MOVQ	AX, g_stackguard0(DX)
   362  	MOVQ	AX, g_stackguard1(DX)
   363  
   364  	// Set up tls.
   365  	LEAQ	m_tls(CX), SI
   366  	MOVQ	SI, 0x28(GS)
   367  	MOVQ	CX, g_m(DX)
   368  	MOVQ	DX, g(SI)
   369  
   370  	// Someday the convention will be D is always cleared.
   371  	CLD
   372  
   373  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   374  	CALL	runtime·mstart(SB)
   375  
   376  	XORL	AX, AX			// return 0 == success
   377  	RET
   378  
   379  // set tls base to DI
   380  TEXT runtime·settls(SB),NOSPLIT,$0
   381  	MOVQ	DI, 0x28(GS)
   382  	RET
   383  
   384  // func onosstack(fn unsafe.Pointer, arg uint32)
   385  TEXT runtime·onosstack(SB),NOSPLIT,$0
   386  	MOVQ	fn+0(FP), AX		// to hide from 6l
   387  	MOVL	arg+8(FP), BX
   388  
   389  	// Execute call on m->g0 stack, in case we are not actually
   390  	// calling a system call wrapper, like when running under WINE.
   391  	get_tls(R15)
   392  	CMPQ	R15, $0
   393  	JNE	3(PC)
   394  	// Not a Go-managed thread. Do not switch stack.
   395  	CALL	AX
   396  	RET
   397  
   398  	MOVQ	g(R15), R13
   399  	MOVQ	g_m(R13), R13
   400  
   401  	// leave pc/sp for cpu profiler
   402  	MOVQ	(SP), R12
   403  	MOVQ	R12, m_libcallpc(R13)
   404  	MOVQ	g(R15), R12
   405  	MOVQ	R12, m_libcallg(R13)
   406  	// sp must be the last, because once async cpu profiler finds
   407  	// all three values to be non-zero, it will use them
   408  	LEAQ	usec+0(FP), R12
   409  	MOVQ	R12, m_libcallsp(R13)
   410  
   411  	MOVQ	m_g0(R13), R14
   412  	CMPQ	g(R15), R14
   413  	JNE	switch
   414  	// executing on m->g0 already
   415  	CALL	AX
   416  	JMP	ret
   417  
   418  switch:
   419  	// Switch to m->g0 stack and back.
   420  	MOVQ	(g_sched+gobuf_sp)(R14), R14
   421  	MOVQ	SP, -8(R14)
   422  	LEAQ	-8(R14), SP
   423  	CALL	AX
   424  	MOVQ	0(SP), SP
   425  
   426  ret:
   427  	MOVQ	$0, m_libcallsp(R13)
   428  	RET
   429  
   430  // Runs on OS stack. duration (in 100ns units) is in BX.
   431  // The function leaves room for 4 syscall parameters
   432  // (as per windows amd64 calling convention).
   433  TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48
   434  	MOVQ	SP, AX
   435  	ANDQ	$~15, SP	// alignment as per Windows requirement
   436  	MOVQ	AX, 40(SP)
   437  	// Want negative 100ns units.
   438  	NEGQ	BX
   439  	LEAQ	32(SP), R8  // ptime
   440  	MOVQ	BX, (R8)
   441  	MOVQ	$-1, CX // handle
   442  	MOVQ	$0, DX // alertable
   443  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   444  	CALL	AX
   445  	MOVQ	40(SP), SP
   446  	RET
   447  
   448  // Runs on OS stack.
   449  TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
   450  	MOVQ	SP, AX
   451  	ANDQ	$~15, SP	// alignment as per Windows requirement
   452  	SUBQ	$(48), SP	// room for SP and 4 args as per Windows requirement
   453  				// plus one extra word to keep stack 16 bytes aligned
   454  	MOVQ	AX, 32(SP)
   455  	MOVQ	runtime·_SwitchToThread(SB), AX
   456  	CALL	AX
   457  	MOVQ	32(SP), SP
   458  	RET
   459  
   460  // func now() (sec int64, nsec int32)
   461  TEXT time·now(SB),NOSPLIT,$8-12
   462  	CALL	runtime·unixnano(SB)
   463  	MOVQ	0(SP), AX
   464  
   465  	// generated code for
   466  	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 }
   467  	// adapted to reduce duplication
   468  	MOVQ	AX, CX
   469  	MOVQ	$1360296554856532783, AX
   470  	MULQ	CX
   471  	ADDQ	CX, DX
   472  	RCRQ	$1, DX
   473  	SHRQ	$29, DX
   474  	MOVQ	DX, sec+0(FP)
   475  	IMULQ	$1000000000, DX
   476  	SUBQ	DX, CX
   477  	MOVL	CX, nsec+8(FP)
   478  	RET
   479