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  // faster get/set last error
    16  TEXT runtime·getlasterror(SB),NOSPLIT,$0
    17  	MOVQ	0x30(GS), AX
    18  	MOVL	0x68(AX), AX
    19  	MOVL	AX, ret+0(FP)
    20  	RET
    21  
    22  // Called by Windows as a Vectored Exception Handler (VEH).
    23  // CX is pointer to struct containing
    24  // exception record and context pointers.
    25  // DX is the kind of sigtramp function.
    26  // Return value of sigtrampgo is stored in AX.
    27  TEXT sigtramp<>(SB),NOSPLIT,$0-0
    28  	// Switch from the host ABI to the Go ABI.
    29  	PUSH_REGS_HOST_TO_ABI0()
    30  
    31  	// Set up ABIInternal environment: cleared X15 and R14.
    32  	// R14 is cleared in case there's a non-zero value in there
    33  	// if called from a non-go thread.
    34  	XORPS	X15, X15
    35  	XORQ	R14, R14
    36  
    37  	get_tls(AX)
    38  	CMPQ	AX, $0
    39  	JE	2(PC)
    40  	// Exception from Go thread, set R14.
    41  	MOVQ	g(AX), R14
    42  
    43  	// Reserve space for spill slots.
    44  	ADJSP	$16
    45  	MOVQ	CX, AX
    46  	MOVQ	DX, BX
    47  	// Calling ABIInternal because TLS might be nil.
    48  	CALL	runtime·sigtrampgo<ABIInternal>(SB)
    49  	// Return value is already stored in AX.
    50  
    51  	ADJSP	$-16
    52  
    53  	POP_REGS_HOST_TO_ABI0()
    54  	RET
    55  
    56  // Trampoline to resume execution from exception handler.
    57  // This is part of the control flow guard workaround.
    58  // It switches stacks and jumps to the continuation address.
    59  // R8 and R9 are set above at the end of sigtrampgo
    60  // in the context that starts executing at sigresume.
    61  TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
    62  	MOVQ	R8, SP
    63  	JMP	R9
    64  
    65  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
    66  	// PExceptionPointers already on CX
    67  	MOVQ	$const_callbackVEH, DX
    68  	JMP	sigtramp<>(SB)
    69  
    70  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
    71  	// PExceptionPointers already on CX
    72  	MOVQ	$const_callbackFirstVCH, DX
    73  	JMP	sigtramp<>(SB)
    74  
    75  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
    76  	// PExceptionPointers already on CX
    77  	MOVQ	$const_callbackLastVCH, DX
    78  	JMP	sigtramp<>(SB)
    79  
    80  TEXT runtime·sehtramp(SB),NOSPLIT,$40-0
    81  	// CX: PEXCEPTION_RECORD ExceptionRecord
    82  	// DX: ULONG64 EstablisherFrame
    83  	// R8: PCONTEXT ContextRecord
    84  	// R9: PDISPATCHER_CONTEXT DispatcherContext
    85  	// Switch from the host ABI to the Go ABI.
    86  	PUSH_REGS_HOST_TO_ABI0()
    87  
    88  	get_tls(AX)
    89  	CMPQ	AX, $0
    90  	JNE	2(PC)
    91  	// This shouldn't happen, sehtramp is only attached to functions
    92  	// called from Go, and exception handlers are only called from
    93  	// the thread that threw the exception.
    94  	INT	$3
    95  
    96  	// Exception from Go thread, set R14.
    97  	MOVQ	g(AX), R14
    98  
    99  	ADJSP	$40
   100  	MOVQ	CX, 0(SP)
   101  	MOVQ	DX, 8(SP)
   102  	MOVQ	R8, 16(SP)
   103  	MOVQ	R9, 24(SP)
   104  	CALL	runtime·sehhandler(SB)
   105  	MOVL	32(SP), AX
   106  
   107  	ADJSP	$-40
   108  
   109  	POP_REGS_HOST_TO_ABI0()
   110  	RET
   111  
   112  TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
   113  	// Construct args vector for cgocallback().
   114  	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   115  	// args from the 5th on are on the stack.
   116  	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   117  	// but uninitialized "shadow space" for the first 4 args.
   118  	// The values are in registers.
   119  	MOVQ	CX, (16+0)(SP)
   120  	MOVQ	DX, (16+8)(SP)
   121  	MOVQ	R8, (16+16)(SP)
   122  	MOVQ	R9, (16+24)(SP)
   123  	// R8 = address of args vector
   124  	LEAQ	(16+0)(SP), R8
   125  
   126  	// remove return address from stack, we are not returning to callbackasm, but to its caller.
   127  	MOVQ	0(SP), AX
   128  	ADDQ	$8, SP
   129  
   130  	// determine index into runtime·cbs table
   131  	MOVQ	$runtime·callbackasm(SB), DX
   132  	SUBQ	DX, AX
   133  	MOVQ	$0, DX
   134  	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   135  	DIVL	CX
   136  	SUBQ	$1, AX	// subtract 1 because return PC is to the next slot
   137  
   138  	// Switch from the host ABI to the Go ABI.
   139  	PUSH_REGS_HOST_TO_ABI0()
   140  
   141  	// Create a struct callbackArgs on our stack to be passed as
   142  	// the "frame" to cgocallback and on to callbackWrap.
   143  	SUBQ	$(24+callbackArgs__size), SP
   144  	MOVQ	AX, (24+callbackArgs_index)(SP) 	// callback index
   145  	MOVQ	R8, (24+callbackArgs_args)(SP)  	// address of args vector
   146  	MOVQ	$0, (24+callbackArgs_result)(SP)	// result
   147  	LEAQ	24(SP), AX
   148  	// Call cgocallback, which will call callbackWrap(frame).
   149  	MOVQ	$0, 16(SP)	// context
   150  	MOVQ	AX, 8(SP)	// frame (address of callbackArgs)
   151  	LEAQ	·callbackWrap<ABIInternal>(SB), BX	// cgocallback takes an ABIInternal entry-point
   152  	MOVQ	BX, 0(SP)	// PC of function value to call (callbackWrap)
   153  	CALL	·cgocallback(SB)
   154  	// Get callback result.
   155  	MOVQ	(24+callbackArgs_result)(SP), AX
   156  	ADDQ	$(24+callbackArgs__size), SP
   157  
   158  	POP_REGS_HOST_TO_ABI0()
   159  
   160  	// The return value was placed in AX above.
   161  	RET
   162  
   163  // uint32 tstart_stdcall(M *newm);
   164  TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
   165  	// Switch from the host ABI to the Go ABI.
   166  	PUSH_REGS_HOST_TO_ABI0()
   167  
   168  	// CX contains first arg newm
   169  	MOVQ	m_g0(CX), DX		// g
   170  
   171  	// Layout new m scheduler stack on os stack.
   172  	MOVQ	SP, AX
   173  	MOVQ	AX, (g_stack+stack_hi)(DX)
   174  	SUBQ	$(64*1024), AX		// initial stack size (adjusted later)
   175  	MOVQ	AX, (g_stack+stack_lo)(DX)
   176  	ADDQ	$const_stackGuard, AX
   177  	MOVQ	AX, g_stackguard0(DX)
   178  	MOVQ	AX, g_stackguard1(DX)
   179  
   180  	// Set up tls.
   181  	LEAQ	m_tls(CX), DI
   182  	MOVQ	CX, g_m(DX)
   183  	MOVQ	DX, g(DI)
   184  	CALL	runtime·settls(SB) // clobbers CX
   185  
   186  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   187  	CALL	runtime·mstart(SB)
   188  
   189  	POP_REGS_HOST_TO_ABI0()
   190  
   191  	XORL	AX, AX			// return 0 == success
   192  	RET
   193  
   194  // set tls base to DI
   195  TEXT runtime·settls(SB),NOSPLIT,$0
   196  	MOVQ	runtime·tls_g(SB), CX
   197  	MOVQ	DI, 0(CX)(GS)
   198  	RET
   199  
   200  TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   201  	MOVQ	$_INTERRUPT_TIME, DI
   202  	MOVQ	time_lo(DI), AX
   203  	IMULQ	$100, AX
   204  	MOVQ	AX, ret+0(FP)
   205  	RET
   206  
   207  // func osSetupTLS(mp *m)
   208  // Setup TLS. for use by needm on Windows.
   209  TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
   210  	MOVQ	mp+0(FP), AX
   211  	LEAQ	m_tls(AX), DI
   212  	CALL	runtime·settls(SB)
   213  	RET
   214  
   215  // This is called from rt0_go, which runs on the system stack
   216  // using the initial stack allocated by the OS.
   217  TEXT runtime·wintls(SB),NOSPLIT,$0
   218  	// Allocate a TLS slot to hold g across calls to external code
   219  	MOVQ	SP, AX
   220  	ANDQ	$~15, SP	// alignment as per Windows requirement
   221  	SUBQ	$48, SP	// room for SP and 4 args as per Windows requirement
   222  			// plus one extra word to keep stack 16 bytes aligned
   223  	MOVQ	AX, 32(SP)
   224  	MOVQ	runtime·_TlsAlloc(SB), AX
   225  	CALL	AX
   226  	MOVQ	32(SP), SP
   227  
   228  	MOVQ	AX, CX	// TLS index
   229  
   230  	// Assert that slot is less than 64 so we can use _TEB->TlsSlots
   231  	CMPQ	CX, $64
   232  	JB	ok
   233  
   234  	// Fallback to the TEB arbitrary pointer.
   235  	// TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
   236  	MOVQ	$TEB_ArbitraryPtr, CX
   237  	JMP	settls
   238  ok:
   239  	// Convert the TLS index at CX into
   240  	// an offset from TEB_TlsSlots.
   241  	SHLQ	$3, CX
   242  
   243  	// Save offset from TLS into tls_g.
   244  	ADDQ	$TEB_TlsSlots, CX
   245  settls:
   246  	MOVQ	CX, runtime·tls_g(SB)
   247  	RET
   248  

View as plain text