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

View as plain text