github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/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,$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,$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,$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,$0
   194  	MOVQ	$runtime·exceptionhandler(SB), AX
   195  	JMP	runtime·sigtramp(SB)
   196  
   197  TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
   198  	MOVQ	$runtime·firstcontinuehandler(SB), AX
   199  	JMP	runtime·sigtramp(SB)
   200  
   201  TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
   202  	MOVQ	$runtime·lastcontinuehandler(SB), AX
   203  	JMP	runtime·sigtramp(SB)
   204  
   205  TEXT runtime·ctrlhandler(SB),NOSPLIT,$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,$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,$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
   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
   243  	LEAQ	g__size(SP), BX
   244  	MOVQ	BX, g_m(SP)
   245  
   246  	LEAQ	-8192(SP), CX
   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	32(BP)			// arg for handler
   254  	CALL	16(BP)
   255  	POPQ	CX
   256  
   257  	get_tls(CX)
   258  	MOVQ	g(CX), CX
   259  	MOVQ	(g_stack+stack_hi)(CX), SP
   260  	POPQ	0x28(GS)
   261  	POPQ	DI
   262  	POPQ	SI
   263  	POPQ	BX
   264  	POPQ	BP
   265  	RET
   266  
   267  GLOBL runtime·cbctxts(SB), NOPTR, $8
   268  
   269  TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   270  	// Construct args vector for cgocallback().
   271  	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   272  	// args from the 5th on are on the stack.
   273  	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   274  	// but uninitialized "shadow space" for the first 4 args.
   275  	// The values are in registers.
   276    	MOVQ	CX, (16+0)(SP)
   277    	MOVQ	DX, (16+8)(SP)
   278    	MOVQ	R8, (16+16)(SP)
   279    	MOVQ	R9, (16+24)(SP)
   280  
   281  	// remove return address from stack, we are not returning there
   282    	MOVQ	0(SP), AX
   283  	ADDQ	$8, SP
   284  
   285  	// determine index into runtime·cbctxts table
   286  	MOVQ	$runtime·callbackasm(SB), DX
   287  	SUBQ	DX, AX
   288  	MOVQ	$0, DX
   289  	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   290  	DIVL	CX,
   291  
   292  	// find correspondent runtime·cbctxts table entry
   293  	MOVQ	runtime·cbctxts(SB), CX
   294  	MOVQ	-8(CX)(AX*8), AX
   295  
   296  	// extract callback context
   297  	MOVQ	wincallbackcontext_argsize(AX), DX
   298  	MOVQ	wincallbackcontext_gobody(AX), AX
   299  
   300  	// preserve whatever's at the memory location that
   301  	// the callback will use to store the return value
   302  	LEAQ	8(SP), CX       // args vector, skip return address
   303  	PUSHQ	0(CX)(DX*1)     // store 8 bytes from just after the args array
   304  	ADDQ	$8, DX          // extend argsize by size of return value
   305  
   306  	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
   307  	// as required by windows callback convention.
   308  	PUSHFQ
   309  	SUBQ	$64, SP
   310  	MOVQ	DI, 56(SP)
   311  	MOVQ	SI, 48(SP)
   312  	MOVQ	BP, 40(SP)
   313  	MOVQ	BX, 32(SP)
   314  	MOVQ	R12, 24(SP)
   315  	MOVQ	R13, 16(SP)
   316  	MOVQ	R14, 8(SP)
   317  	MOVQ	R15, 0(SP)
   318  
   319  	// prepare call stack.  use SUBQ to hide from stack frame checks
   320  	// cgocallback(Go func, void *frame, uintptr framesize)
   321  	SUBQ	$24, SP
   322  	MOVQ	DX, 16(SP)	// argsize (including return value)
   323  	MOVQ	CX, 8(SP)	// callback parameters
   324  	MOVQ	AX, 0(SP)	// address of target Go function
   325  	CLD
   326  	CALL	runtime·cgocallback_gofunc(SB)
   327  	MOVQ	0(SP), AX
   328  	MOVQ	8(SP), CX
   329  	MOVQ	16(SP), DX
   330  	ADDQ	$24, SP
   331  
   332  	// restore registers as required for windows callback
   333  	MOVQ	0(SP), R15
   334  	MOVQ	8(SP), R14
   335  	MOVQ	16(SP), R13
   336  	MOVQ	24(SP), R12
   337  	MOVQ	32(SP), BX
   338  	MOVQ	40(SP), BP
   339  	MOVQ	48(SP), SI
   340  	MOVQ	56(SP), DI
   341  	ADDQ	$64, SP
   342  	POPFQ
   343  
   344  	MOVL	-8(CX)(DX*1), AX  // return value
   345  	POPQ	-8(CX)(DX*1)      // restore bytes just after the args
   346  	RET
   347  
   348  // uint32 tstart_stdcall(M *newm);
   349  TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   350  	// CX contains first arg newm
   351  	MOVQ	m_g0(CX), DX		// g
   352  
   353  	// Layout new m scheduler stack on os stack.
   354  	MOVQ	SP, AX
   355  	MOVQ	AX, (g_stack+stack_hi)(DX)
   356  	SUBQ	$(64*1024), AX		// stack size
   357  	MOVQ	AX, (g_stack+stack_lo)(DX)
   358  	ADDQ	$const__StackGuard, AX
   359  	MOVQ	AX, g_stackguard0(DX)
   360  	MOVQ	AX, g_stackguard1(DX)
   361  
   362  	// Set up tls.
   363  	LEAQ	m_tls(CX), SI
   364  	MOVQ	SI, 0x28(GS)
   365  	MOVQ	CX, g_m(DX)
   366  	MOVQ	DX, g(SI)
   367  
   368  	// Someday the convention will be D is always cleared.
   369  	CLD
   370  
   371  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   372  	CALL	runtime·mstart(SB)
   373  
   374  	XORL	AX, AX			// return 0 == success
   375  	RET
   376  
   377  // set tls base to DI
   378  TEXT runtime·settls(SB),NOSPLIT,$0
   379  	MOVQ	DI, 0x28(GS)
   380  	RET
   381  
   382  // Sleep duration is in 100ns units.
   383  TEXT runtime·usleep1(SB),NOSPLIT,$0
   384  	MOVL	usec+0(FP), BX
   385  	MOVQ	$runtime·usleep2(SB), AX // to hide from 6l
   386  
   387  	// Execute call on m->g0 stack, in case we are not actually
   388  	// calling a system call wrapper, like when running under WINE.
   389  	get_tls(R15)
   390  	CMPQ	R15, $0
   391  	JNE	3(PC)
   392  	// Not a Go-managed thread. Do not switch stack.
   393  	CALL	AX
   394  	RET
   395  
   396  	MOVQ	g(R15), R13
   397  	MOVQ	g_m(R13), R13
   398  
   399  	// leave pc/sp for cpu profiler
   400  	MOVQ	(SP), R12
   401  	MOVQ	R12, m_libcallpc(R13)
   402  	MOVQ	g(R15), R12
   403  	MOVQ	R12, m_libcallg(R13)
   404  	// sp must be the last, because once async cpu profiler finds
   405  	// all three values to be non-zero, it will use them
   406  	LEAQ	usec+0(FP), R12
   407  	MOVQ	R12, m_libcallsp(R13)
   408  
   409  	MOVQ	m_g0(R13), R14
   410  	CMPQ	g(R15), R14
   411  	JNE	switch
   412  	// executing on m->g0 already
   413  	CALL	AX
   414  	JMP	ret
   415  
   416  switch:
   417  	// Switch to m->g0 stack and back.
   418  	MOVQ	(g_sched+gobuf_sp)(R14), R14
   419  	MOVQ	SP, -8(R14)
   420  	LEAQ	-8(R14), SP
   421  	CALL	AX
   422  	MOVQ	0(SP), SP
   423  
   424  ret:
   425  	MOVQ	$0, m_libcallsp(R13)
   426  	RET
   427  
   428  // Runs on OS stack. duration (in 100ns units) is in BX.
   429  TEXT runtime·usleep2(SB),NOSPLIT,$16
   430  	MOVQ	SP, AX
   431  	ANDQ	$~15, SP	// alignment as per Windows requirement
   432  	MOVQ	AX, 8(SP)
   433  	// Want negative 100ns units.
   434  	NEGQ	BX
   435  	MOVQ	SP, R8 // ptime
   436  	MOVQ	BX, (R8)
   437  	MOVQ	$-1, CX // handle
   438  	MOVQ	$0, DX // alertable
   439  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   440  	CALL	AX
   441  	MOVQ	8(SP), SP
   442  	RET
   443  
   444  // func now() (sec int64, nsec int32)
   445  TEXT time·now(SB),NOSPLIT,$8-12
   446  	CALL	runtime·unixnano(SB)
   447  	MOVQ	0(SP), AX
   448  
   449  	// generated code for
   450  	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
   451  	// adapted to reduce duplication
   452  	MOVQ	AX, CX
   453  	MOVQ	$1360296554856532783, AX
   454  	MULQ	CX
   455  	ADDQ	CX, DX
   456  	RCRQ	$1, DX
   457  	SHRQ	$29, DX
   458  	MOVQ	DX, sec+0(FP)
   459  	IMULQ	$1000000000, DX
   460  	SUBQ	DX, CX
   461  	MOVL	CX, nsec+8(FP)
   462  	RET
   463