...

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#include "time_windows.h"
     9#include "cgo/abi_amd64.h"
    10
    11// Offsets into Thread Environment Block (pointer in GS)
    12#define TEB_TlsSlots 0x1480
    13#define TEB_ArbitraryPtr 0x28
    14
    15TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
    16	MOVQ	AX, CX
    17	JMP	runtime·asmstdcall(SB)
    18
    19// void runtime·asmstdcall(void *c);
    20TEXT runtime·asmstdcall(SB),NOSPLIT,$16
    21	MOVQ	SP, AX
    22	ANDQ	$~15, SP	// alignment as per Windows requirement
    23	MOVQ	AX, 8(SP)
    24	MOVQ	CX, 0(SP)	// asmcgocall will put first argument into CX.
    25
    26	MOVQ	libcall_fn(CX), AX
    27	MOVQ	libcall_args(CX), SI
    28	MOVQ	libcall_n(CX), CX
    29
    30	// SetLastError(0).
    31	MOVQ	0x30(GS), DI
    32	MOVL	$0, 0x68(DI)
    33
    34	SUBQ	$(const_maxArgs*8), SP	// room for args
    35
    36	// Fast version, do not store args on the stack.
    37	CMPL	CX, $0;	JE	_0args
    38	CMPL	CX, $1;	JE	_1args
    39	CMPL	CX, $2;	JE	_2args
    40	CMPL	CX, $3;	JE	_3args
    41	CMPL	CX, $4;	JE	_4args
    42
    43	// Check we have enough room for args.
    44	CMPL	CX, $const_maxArgs
    45	JLE	2(PC)
    46	INT	$3			// not enough room -> crash
    47
    48	// Copy args to the stack.
    49	MOVQ	SP, DI
    50	CLD
    51	REP; MOVSQ
    52	MOVQ	SP, SI
    53
    54	// Load first 4 args into correspondent registers.
    55	// Floating point arguments are passed in the XMM
    56	// registers. Set them here in case any of the arguments
    57	// are floating point values. For details see
    58	//	https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
    59_4args:
    60	MOVQ	24(SI), R9
    61	MOVQ	R9, X3
    62_3args:
    63	MOVQ	16(SI), R8
    64	MOVQ	R8, X2
    65_2args:
    66	MOVQ	8(SI), DX
    67	MOVQ	DX, X1
    68_1args:
    69	MOVQ	0(SI), CX
    70	MOVQ	CX, X0
    71_0args:
    72
    73	// Call stdcall function.
    74	CALL	AX
    75
    76	ADDQ	$(const_maxArgs*8), SP
    77
    78	// Return result.
    79	MOVQ	0(SP), CX
    80	MOVQ	8(SP), SP
    81	MOVQ	AX, libcall_r1(CX)
    82	// Floating point return values are returned in XMM0. Setting r2 to this
    83	// value in case this call returned a floating point value. For details,
    84	// see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
    85	MOVQ    X0, libcall_r2(CX)
    86
    87	// GetLastError().
    88	MOVQ	0x30(GS), DI
    89	MOVL	0x68(DI), AX
    90	MOVQ	AX, libcall_err(CX)
    91
    92	RET
    93
    94// faster get/set last error
    95TEXT runtime·getlasterror(SB),NOSPLIT,$0
    96	MOVQ	0x30(GS), AX
    97	MOVL	0x68(AX), AX
    98	MOVL	AX, ret+0(FP)
    99	RET
   100
   101// Called by Windows as a Vectored Exception Handler (VEH).
   102// CX is pointer to struct containing
   103// exception record and context pointers.
   104// DX is the kind of sigtramp function.
   105// Return value of sigtrampgo is stored in AX.
   106TEXT sigtramp<>(SB),NOSPLIT,$0-0
   107	// Switch from the host ABI to the Go ABI.
   108	PUSH_REGS_HOST_TO_ABI0()
   109
   110	// Set up ABIInternal environment: cleared X15 and R14.
   111	// R14 is cleared in case there's a non-zero value in there
   112	// if called from a non-go thread.
   113	XORPS	X15, X15
   114	XORQ	R14, R14
   115
   116	get_tls(AX)
   117	CMPQ	AX, $0
   118	JE	2(PC)
   119	// Exception from Go thread, set R14.
   120	MOVQ	g(AX), R14
   121
   122	// Reserve space for spill slots.
   123	ADJSP	$16
   124	MOVQ	CX, AX
   125	MOVQ	DX, BX
   126	// Calling ABIInternal because TLS might be nil.
   127	CALL	runtime·sigtrampgo<ABIInternal>(SB)
   128	// Return value is already stored in AX.
   129
   130	ADJSP	$-16
   131
   132	POP_REGS_HOST_TO_ABI0()
   133	RET
   134
   135// Trampoline to resume execution from exception handler.
   136// This is part of the control flow guard workaround.
   137// It switches stacks and jumps to the continuation address.
   138// R8 and R9 are set above at the end of sigtrampgo
   139// in the context that starts executing at sigresume.
   140TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
   141	MOVQ	R8, SP
   142	JMP	R9
   143
   144TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   145	// PExceptionPointers already on CX
   146	MOVQ	$const_callbackVEH, DX
   147	JMP	sigtramp<>(SB)
   148
   149TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   150	// PExceptionPointers already on CX
   151	MOVQ	$const_callbackFirstVCH, DX
   152	JMP	sigtramp<>(SB)
   153
   154TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   155	// PExceptionPointers already on CX
   156	MOVQ	$const_callbackLastVCH, DX
   157	JMP	sigtramp<>(SB)
   158
   159TEXT runtime·sehtramp(SB),NOSPLIT,$40-0
   160	// CX: PEXCEPTION_RECORD ExceptionRecord
   161	// DX: ULONG64 EstablisherFrame
   162	// R8: PCONTEXT ContextRecord
   163	// R9: PDISPATCHER_CONTEXT DispatcherContext
   164	// Switch from the host ABI to the Go ABI.
   165	PUSH_REGS_HOST_TO_ABI0()
   166
   167	get_tls(AX)
   168	CMPQ	AX, $0
   169	JNE	2(PC)
   170	// This shouldn't happen, sehtramp is only attached to functions
   171	// called from Go, and exception handlers are only called from
   172	// the thread that threw the exception.
   173	INT	$3
   174
   175	// Exception from Go thread, set R14.
   176	MOVQ	g(AX), R14
   177
   178	ADJSP	$40
   179	MOVQ	CX, 0(SP)
   180	MOVQ	DX, 8(SP)
   181	MOVQ	R8, 16(SP)
   182	MOVQ	R9, 24(SP)
   183	CALL	runtime·sehhandler(SB)
   184	MOVL	32(SP), AX
   185
   186	ADJSP	$-40
   187
   188	POP_REGS_HOST_TO_ABI0()
   189	RET
   190
   191TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
   192	// Construct args vector for cgocallback().
   193	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   194	// args from the 5th on are on the stack.
   195	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   196	// but uninitialized "shadow space" for the first 4 args.
   197	// The values are in registers.
   198	MOVQ	CX, (16+0)(SP)
   199	MOVQ	DX, (16+8)(SP)
   200	MOVQ	R8, (16+16)(SP)
   201	MOVQ	R9, (16+24)(SP)
   202	// R8 = address of args vector
   203	LEAQ	(16+0)(SP), R8
   204
   205	// remove return address from stack, we are not returning to callbackasm, but to its caller.
   206	MOVQ	0(SP), AX
   207	ADDQ	$8, SP
   208
   209	// determine index into runtime·cbs table
   210	MOVQ	$runtime·callbackasm(SB), DX
   211	SUBQ	DX, AX
   212	MOVQ	$0, DX
   213	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   214	DIVL	CX
   215	SUBQ	$1, AX	// subtract 1 because return PC is to the next slot
   216
   217	// Switch from the host ABI to the Go ABI.
   218	PUSH_REGS_HOST_TO_ABI0()
   219
   220	// Create a struct callbackArgs on our stack to be passed as
   221	// the "frame" to cgocallback and on to callbackWrap.
   222	SUBQ	$(24+callbackArgs__size), SP
   223	MOVQ	AX, (24+callbackArgs_index)(SP) 	// callback index
   224	MOVQ	R8, (24+callbackArgs_args)(SP)  	// address of args vector
   225	MOVQ	$0, (24+callbackArgs_result)(SP)	// result
   226	LEAQ	24(SP), AX
   227	// Call cgocallback, which will call callbackWrap(frame).
   228	MOVQ	$0, 16(SP)	// context
   229	MOVQ	AX, 8(SP)	// frame (address of callbackArgs)
   230	LEAQ	·callbackWrap<ABIInternal>(SB), BX	// cgocallback takes an ABIInternal entry-point
   231	MOVQ	BX, 0(SP)	// PC of function value to call (callbackWrap)
   232	CALL	·cgocallback(SB)
   233	// Get callback result.
   234	MOVQ	(24+callbackArgs_result)(SP), AX
   235	ADDQ	$(24+callbackArgs__size), SP
   236
   237	POP_REGS_HOST_TO_ABI0()
   238
   239	// The return value was placed in AX above.
   240	RET
   241
   242// uint32 tstart_stdcall(M *newm);
   243TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
   244	// Switch from the host ABI to the Go ABI.
   245	PUSH_REGS_HOST_TO_ABI0()
   246
   247	// CX contains first arg newm
   248	MOVQ	m_g0(CX), DX		// g
   249
   250	// Layout new m scheduler stack on os stack.
   251	MOVQ	SP, AX
   252	MOVQ	AX, (g_stack+stack_hi)(DX)
   253	SUBQ	$(64*1024), AX		// initial stack size (adjusted later)
   254	MOVQ	AX, (g_stack+stack_lo)(DX)
   255	ADDQ	$const_stackGuard, AX
   256	MOVQ	AX, g_stackguard0(DX)
   257	MOVQ	AX, g_stackguard1(DX)
   258
   259	// Set up tls.
   260	LEAQ	m_tls(CX), DI
   261	MOVQ	CX, g_m(DX)
   262	MOVQ	DX, g(DI)
   263	CALL	runtime·settls(SB) // clobbers CX
   264
   265	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   266	CALL	runtime·mstart(SB)
   267
   268	POP_REGS_HOST_TO_ABI0()
   269
   270	XORL	AX, AX			// return 0 == success
   271	RET
   272
   273// set tls base to DI
   274TEXT runtime·settls(SB),NOSPLIT,$0
   275	MOVQ	runtime·tls_g(SB), CX
   276	MOVQ	DI, 0(CX)(GS)
   277	RET
   278
   279TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   280	MOVQ	$_INTERRUPT_TIME, DI
   281	MOVQ	time_lo(DI), AX
   282	IMULQ	$100, AX
   283	MOVQ	AX, ret+0(FP)
   284	RET
   285
   286// func osSetupTLS(mp *m)
   287// Setup TLS. for use by needm on Windows.
   288TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
   289	MOVQ	mp+0(FP), AX
   290	LEAQ	m_tls(AX), DI
   291	CALL	runtime·settls(SB)
   292	RET
   293
   294// This is called from rt0_go, which runs on the system stack
   295// using the initial stack allocated by the OS.
   296TEXT runtime·wintls(SB),NOSPLIT,$0
   297	// Allocate a TLS slot to hold g across calls to external code
   298	MOVQ	SP, AX
   299	ANDQ	$~15, SP	// alignment as per Windows requirement
   300	SUBQ	$48, SP	// room for SP and 4 args as per Windows requirement
   301			// plus one extra word to keep stack 16 bytes aligned
   302	MOVQ	AX, 32(SP)
   303	MOVQ	runtime·_TlsAlloc(SB), AX
   304	CALL	AX
   305	MOVQ	32(SP), SP
   306
   307	MOVQ	AX, CX	// TLS index
   308
   309	// Assert that slot is less than 64 so we can use _TEB->TlsSlots
   310	CMPQ	CX, $64
   311	JB	ok
   312
   313	// Fallback to the TEB arbitrary pointer.
   314	// TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
   315	MOVQ	$TEB_ArbitraryPtr, CX
   316	JMP	settls
   317ok:
   318	// Convert the TLS index at CX into
   319	// an offset from TEB_TlsSlots.
   320	SHLQ	$3, CX
   321
   322	// Save offset from TLS into tls_g.
   323	ADDQ	$TEB_TlsSlots, CX
   324settls:
   325	MOVQ	CX, runtime·tls_g(SB)
   326	RET

View as plain text