Black Lives Matter. Support the Equal Justice Initiative.

Text file src/runtime/sys_windows_amd64.s

Documentation: runtime

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

View as plain text