...

Text file src/runtime/sys_windows_amd64.s

     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 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	sigtramp<>(SB)
   204	
   205	TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   206		MOVQ	$runtime·firstcontinuehandler(SB), AX
   207		JMP	sigtramp<>(SB)
   208	
   209	TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   210		MOVQ	$runtime·lastcontinuehandler(SB), AX
   211		JMP	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		MOVQ	-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		// initial stack size (adjusted later)
   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	fn+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 https://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		CMPB	runtime·useQPCTime(SB), $0
   478		JNE	useQPC
   479		MOVQ	$_INTERRUPT_TIME, DI
   480	loop:
   481		MOVL	time_hi1(DI), AX
   482		MOVL	time_lo(DI), BX
   483		MOVL	time_hi2(DI), CX
   484		CMPL	AX, CX
   485		JNE	loop
   486		SHLQ	$32, CX
   487		ORQ	BX, CX
   488		IMULQ	$100, CX
   489		MOVQ	CX, ret+0(FP)
   490		RET
   491	useQPC:
   492		JMP	runtime·nanotimeQPC(SB)
   493		RET
   494	
   495	TEXT time·now(SB),NOSPLIT,$0-24
   496		CMPB	runtime·useQPCTime(SB), $0
   497		JNE	useQPC
   498		MOVQ	$_INTERRUPT_TIME, DI
   499	loop:
   500		MOVL	time_hi1(DI), AX
   501		MOVL	time_lo(DI), BX
   502		MOVL	time_hi2(DI), CX
   503		CMPL	AX, CX
   504		JNE	loop
   505		SHLQ	$32, AX
   506		ORQ	BX, AX
   507		IMULQ	$100, AX
   508		MOVQ	AX, mono+16(FP)
   509	
   510		MOVQ	$_SYSTEM_TIME, DI
   511	wall:
   512		MOVL	time_hi1(DI), AX
   513		MOVL	time_lo(DI), BX
   514		MOVL	time_hi2(DI), CX
   515		CMPL	AX, CX
   516		JNE	wall
   517		SHLQ	$32, AX
   518		ORQ	BX, AX
   519		MOVQ	$116444736000000000, DI
   520		SUBQ	DI, AX
   521		IMULQ	$100, AX
   522	
   523		// generated code for
   524		//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
   525		// adapted to reduce duplication
   526		MOVQ	AX, CX
   527		MOVQ	$1360296554856532783, AX
   528		MULQ	CX
   529		ADDQ	CX, DX
   530		RCRQ	$1, DX
   531		SHRQ	$29, DX
   532		MOVQ	DX, sec+0(FP)
   533		IMULQ	$1000000000, DX
   534		SUBQ	DX, CX
   535		MOVL	CX, nsec+8(FP)
   536		RET
   537	useQPC:
   538		JMP	runtime·nowQPC(SB)
   539		RET

View as plain text