...
Run Format

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
    66	// GetLastError().
    67	MOVQ	0x30(GS), DI
    68	MOVL	0x68(DI), AX
    69	MOVQ	AX, libcall_err(CX)
    70
    71	RET
    72
    73TEXT 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
    96TEXT runtime·getlasterror(SB),NOSPLIT,$0
    97	MOVQ	0x30(GS), AX
    98	MOVL	0x68(AX), AX
    99	MOVL	AX, ret+0(FP)
   100	RET
   101
   102TEXT 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.
   113TEXT 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
   169g0:
   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
   186done:
   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
   201TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   202	MOVQ	$runtime·exceptionhandler(SB), AX
   203	JMP	runtime·sigtramp(SB)
   204
   205TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   206	MOVQ	$runtime·firstcontinuehandler(SB), AX
   207	JMP	runtime·sigtramp(SB)
   208
   209TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   210	MOVQ	$runtime·lastcontinuehandler(SB), AX
   211	JMP	runtime·sigtramp(SB)
   212
   213TEXT 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
   220TEXT 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
   226TEXT 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
   277GLOBL runtime·cbctxts(SB), NOPTR, $8
   278
   279TEXT 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);
   359TEXT 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
   388TEXT runtime·settls(SB),NOSPLIT,$0
   389	MOVQ	DI, 0x28(GS)
   390	RET
   391
   392// func onosstack(fn unsafe.Pointer, arg uint32)
   393TEXT 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
   426switch:
   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
   434ret:
   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).
   441TEXT 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.
   457TEXT 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
   476TEXT runtime·nanotime(SB),NOSPLIT,$0-8
   477	CMPB	runtime·useQPCTime(SB), $0
   478	JNE	useQPC
   479	MOVQ	$_INTERRUPT_TIME, DI
   480loop:
   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
   491useQPC:
   492	JMP	runtime·nanotimeQPC(SB)
   493	RET
   494
   495TEXT time·now(SB),NOSPLIT,$0-24
   496	CMPB	runtime·useQPCTime(SB), $0
   497	JNE	useQPC
   498	MOVQ	$_INTERRUPT_TIME, DI
   499loop:
   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
   511wall:
   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
   537useQPC:
   538	JMP	runtime·nowQPC(SB)
   539	RET

View as plain text