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