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  #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  
    15  TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
    16  	MOVQ	AX, CX
    17  	JMP	runtime·asmstdcall(SB)
    18  
    19  // void runtime·asmstdcall(void *c);
    20  TEXT 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
    95  TEXT 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.
   106  TEXT 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.
   140  TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
   141  	MOVQ	R8, SP
   142  	JMP	R9
   143  
   144  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   145  	// PExceptionPointers already on CX
   146  	MOVQ	$const_callbackVEH, DX
   147  	JMP	sigtramp<>(SB)
   148  
   149  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   150  	// PExceptionPointers already on CX
   151  	MOVQ	$const_callbackFirstVCH, DX
   152  	JMP	sigtramp<>(SB)
   153  
   154  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   155  	// PExceptionPointers already on CX
   156  	MOVQ	$const_callbackLastVCH, DX
   157  	JMP	sigtramp<>(SB)
   158  
   159  TEXT 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  
   191  TEXT 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);
   243  TEXT 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
   274  TEXT runtime·settls(SB),NOSPLIT,$0
   275  	MOVQ	runtime·tls_g(SB), CX
   276  	MOVQ	DI, 0(CX)(GS)
   277  	RET
   278  
   279  TEXT 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.
   288  TEXT 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.
   296  TEXT 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
   317  ok:
   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
   324  settls:
   325  	MOVQ	CX, runtime·tls_g(SB)
   326  	RET
   327  

View as plain text