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  // void runtime·asmstdcall(void *c);
    12  TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
    13  	// asmcgocall will put first argument into CX.
    14  	PUSHQ	CX			// save for later
    15  	MOVQ	libcall_fn(CX), AX
    16  	MOVQ	libcall_args(CX), SI
    17  	MOVQ	libcall_n(CX), CX
    18  
    19  	// SetLastError(0).
    20  	MOVQ	0x30(GS), DI
    21  	MOVL	$0, 0x68(DI)
    22  
    23  	SUBQ	$(const_maxArgs*8), SP	// room for args
    24  
    25  	// Fast version, do not store args on the stack.
    26  	CMPL	CX, $4
    27  	JLE	loadregs
    28  
    29  	// Check we have enough room for args.
    30  	CMPL	CX, $const_maxArgs
    31  	JLE	2(PC)
    32  	INT	$3			// not enough room -> crash
    33  
    34  	// Copy args to the stack.
    35  	MOVQ	SP, DI
    36  	CLD
    37  	REP; MOVSQ
    38  	MOVQ	SP, SI
    39  
    40  loadregs:
    41  	// Load first 4 args into correspondent registers.
    42  	MOVQ	0(SI), CX
    43  	MOVQ	8(SI), DX
    44  	MOVQ	16(SI), R8
    45  	MOVQ	24(SI), R9
    46  	// Floating point arguments are passed in the XMM
    47  	// registers. Set them here in case any of the arguments
    48  	// are floating point values. For details see
    49  	//	https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
    50  	MOVQ	CX, X0
    51  	MOVQ	DX, X1
    52  	MOVQ	R8, X2
    53  	MOVQ	R9, X3
    54  
    55  	// Call stdcall function.
    56  	CALL	AX
    57  
    58  	ADDQ	$(const_maxArgs*8), SP
    59  
    60  	// Return result.
    61  	POPQ	CX
    62  	MOVQ	AX, libcall_r1(CX)
    63  	// Floating point return values are returned in XMM0. Setting r2 to this
    64  	// value in case this call returned a floating point value. For details,
    65  	// see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
    66  	MOVQ    X0, libcall_r2(CX)
    67  
    68  	// GetLastError().
    69  	MOVQ	0x30(GS), DI
    70  	MOVL	0x68(DI), AX
    71  	MOVQ	AX, libcall_err(CX)
    72  
    73  	RET
    74  
    75  TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48
    76  	// stderr
    77  	MOVQ	$-12, CX // stderr
    78  	MOVQ	CX, 0(SP)
    79  	MOVQ	runtime·_GetStdHandle(SB), AX
    80  	CALL	AX
    81  
    82  	MOVQ	AX, CX	// handle
    83  	MOVQ	CX, 0(SP)
    84  	MOVQ	$runtime·badsignalmsg(SB), DX // pointer
    85  	MOVQ	DX, 8(SP)
    86  	MOVL	$runtime·badsignallen(SB), R8 // count
    87  	MOVQ	R8, 16(SP)
    88  	LEAQ	40(SP), R9  // written count
    89  	MOVQ	$0, 0(R9)
    90  	MOVQ	R9, 24(SP)
    91  	MOVQ	$0, 32(SP)	// overlapped
    92  	MOVQ	runtime·_WriteFile(SB), AX
    93  	CALL	AX
    94  
    95  	// Does not return.
    96  	CALL	runtime·abort(SB)
    97  	RET
    98  
    99  // faster get/set last error
   100  TEXT runtime·getlasterror(SB),NOSPLIT,$0
   101  	MOVQ	0x30(GS), AX
   102  	MOVL	0x68(AX), AX
   103  	MOVL	AX, ret+0(FP)
   104  	RET
   105  
   106  // Called by Windows as a Vectored Exception Handler (VEH).
   107  // First argument is pointer to struct containing
   108  // exception record and context pointers.
   109  // Handler function is stored in AX.
   110  // Return 0 for 'not handled', -1 for handled.
   111  TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
   112  	// CX: PEXCEPTION_POINTERS ExceptionInfo
   113  
   114  	// Switch from the host ABI to the Go ABI.
   115  	PUSH_REGS_HOST_TO_ABI0()
   116  	// Make stack space for the rest of the function.
   117  	ADJSP	$48
   118  
   119  	MOVQ	AX, R15	// save handler address
   120  
   121  	// find g
   122  	get_tls(DX)
   123  	CMPQ	DX, $0
   124  	JNE	3(PC)
   125  	MOVQ	$0, AX // continue
   126  	JMP	done
   127  	MOVQ	g(DX), DX
   128  	CMPQ	DX, $0
   129  	JNE	2(PC)
   130  	CALL	runtime·badsignal2(SB)
   131  
   132  	// save g and SP in case of stack switch
   133  	MOVQ	DX, 32(SP) // g
   134  	MOVQ	SP, 40(SP)
   135  
   136  	// do we need to switch to the g0 stack?
   137  	MOVQ	g_m(DX), BX
   138  	MOVQ	m_g0(BX), BX
   139  	CMPQ	DX, BX
   140  	JEQ	g0
   141  
   142  	// switch to g0 stack
   143  	get_tls(BP)
   144  	MOVQ	BX, g(BP)
   145  	MOVQ	(g_sched+gobuf_sp)(BX), DI
   146  	// make room for sighandler arguments
   147  	// and re-save old SP for restoring later.
   148  	// Adjust g0 stack by the space we're using and
   149  	// save SP at the same place on the g0 stack.
   150  	// The 40(DI) here must match the 40(SP) above.
   151  	SUBQ	$(REGS_HOST_TO_ABI0_STACK + 48), DI
   152  	MOVQ	SP, 40(DI)
   153  	MOVQ	DI, SP
   154  
   155  g0:
   156  	MOVQ	0(CX), BX // ExceptionRecord*
   157  	MOVQ	8(CX), CX // Context*
   158  	MOVQ	BX, 0(SP)
   159  	MOVQ	CX, 8(SP)
   160  	MOVQ	DX, 16(SP)
   161  	CALL	R15	// call handler
   162  	// AX is set to report result back to Windows
   163  	MOVL	24(SP), AX
   164  
   165  	// switch back to original stack and g
   166  	// no-op if we never left.
   167  	MOVQ	40(SP), SP
   168  	MOVQ	32(SP), DX
   169  	get_tls(BP)
   170  	MOVQ	DX, g(BP)
   171  
   172  done:
   173  	ADJSP	$-48
   174  	POP_REGS_HOST_TO_ABI0()
   175  
   176  	RET
   177  
   178  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   179  	MOVQ	$runtime·exceptionhandler(SB), AX
   180  	JMP	sigtramp<>(SB)
   181  
   182  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   183  	MOVQ	$runtime·firstcontinuehandler(SB), AX
   184  	JMP	sigtramp<>(SB)
   185  
   186  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   187  	MOVQ	$runtime·lastcontinuehandler(SB), AX
   188  	JMP	sigtramp<>(SB)
   189  
   190  GLOBL runtime·cbctxts(SB), NOPTR, $8
   191  
   192  TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   193  	// Construct args vector for cgocallback().
   194  	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   195  	// args from the 5th on are on the stack.
   196  	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   197  	// but uninitialized "shadow space" for the first 4 args.
   198  	// The values are in registers.
   199    	MOVQ	CX, (16+0)(SP)
   200    	MOVQ	DX, (16+8)(SP)
   201    	MOVQ	R8, (16+16)(SP)
   202    	MOVQ	R9, (16+24)(SP)
   203  	// R8 = address of args vector
   204  	LEAQ	(16+0)(SP), R8
   205  
   206  	// remove return address from stack, we are not returning to callbackasm, but to its caller.
   207    	MOVQ	0(SP), AX
   208  	ADDQ	$8, SP
   209  
   210  	// determine index into runtime·cbs table
   211  	MOVQ	$runtime·callbackasm(SB), DX
   212  	SUBQ	DX, AX
   213  	MOVQ	$0, DX
   214  	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   215  	DIVL	CX
   216  	SUBQ	$1, AX	// subtract 1 because return PC is to the next slot
   217  
   218  	// Switch from the host ABI to the Go ABI.
   219  	PUSH_REGS_HOST_TO_ABI0()
   220  
   221  	// Create a struct callbackArgs on our stack to be passed as
   222  	// the "frame" to cgocallback and on to callbackWrap.
   223  	SUBQ	$(24+callbackArgs__size), SP
   224  	MOVQ	AX, (24+callbackArgs_index)(SP) 	// callback index
   225  	MOVQ	R8, (24+callbackArgs_args)(SP)  	// address of args vector
   226  	MOVQ	$0, (24+callbackArgs_result)(SP)	// result
   227  	LEAQ	24(SP), AX
   228  	// Call cgocallback, which will call callbackWrap(frame).
   229  	MOVQ	$0, 16(SP)	// context
   230  	MOVQ	AX, 8(SP)	// frame (address of callbackArgs)
   231  	LEAQ	·callbackWrap<ABIInternal>(SB), BX	// cgocallback takes an ABIInternal entry-point
   232  	MOVQ	BX, 0(SP)	// PC of function value to call (callbackWrap)
   233  	CALL	·cgocallback(SB)
   234  	// Get callback result.
   235  	MOVQ	(24+callbackArgs_result)(SP), AX
   236  	ADDQ	$(24+callbackArgs__size), SP
   237  
   238  	POP_REGS_HOST_TO_ABI0()
   239  
   240  	// The return value was placed in AX above.
   241  	RET
   242  
   243  // uint32 tstart_stdcall(M *newm);
   244  TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   245  	// Switch from the host ABI to the Go ABI.
   246  	PUSH_REGS_HOST_TO_ABI0()
   247  
   248  	// CX contains first arg newm
   249  	MOVQ	m_g0(CX), DX		// g
   250  
   251  	// Layout new m scheduler stack on os stack.
   252  	MOVQ	SP, AX
   253  	MOVQ	AX, (g_stack+stack_hi)(DX)
   254  	SUBQ	$(64*1024), AX		// initial stack size (adjusted later)
   255  	MOVQ	AX, (g_stack+stack_lo)(DX)
   256  	ADDQ	$const__StackGuard, AX
   257  	MOVQ	AX, g_stackguard0(DX)
   258  	MOVQ	AX, g_stackguard1(DX)
   259  
   260  	// Set up tls.
   261  	LEAQ	m_tls(CX), SI
   262  	MOVQ	SI, 0x28(GS)
   263  	MOVQ	CX, g_m(DX)
   264  	MOVQ	DX, g(SI)
   265  
   266  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   267  	CALL	runtime·mstart(SB)
   268  
   269  	POP_REGS_HOST_TO_ABI0()
   270  
   271  	XORL	AX, AX			// return 0 == success
   272  	RET
   273  
   274  // set tls base to DI
   275  TEXT runtime·settls(SB),NOSPLIT,$0
   276  	MOVQ	DI, 0x28(GS)
   277  	RET
   278  
   279  // Runs on OS stack.
   280  // duration (in -100ns units) is in dt+0(FP).
   281  // g may be nil.
   282  // The function leaves room for 4 syscall parameters
   283  // (as per windows amd64 calling convention).
   284  TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48-4
   285  	MOVLQSX	dt+0(FP), BX
   286  	MOVQ	SP, AX
   287  	ANDQ	$~15, SP	// alignment as per Windows requirement
   288  	MOVQ	AX, 40(SP)
   289  	LEAQ	32(SP), R8  // ptime
   290  	MOVQ	BX, (R8)
   291  	MOVQ	$-1, CX // handle
   292  	MOVQ	$0, DX // alertable
   293  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   294  	CALL	AX
   295  	MOVQ	40(SP), SP
   296  	RET
   297  
   298  // Runs on OS stack. duration (in -100ns units) is in dt+0(FP).
   299  // g is valid.
   300  TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72-4
   301  	MOVLQSX	dt+0(FP), BX
   302  	get_tls(CX)
   303  
   304  	MOVQ	SP, AX
   305  	ANDQ	$~15, SP	// alignment as per Windows requirement
   306  	MOVQ	AX, 64(SP)
   307  
   308  	MOVQ	g(CX), CX
   309  	MOVQ	g_m(CX), CX
   310  	MOVQ	(m_mOS+mOS_highResTimer)(CX), CX	// hTimer
   311  	MOVQ	CX, 48(SP)				// save hTimer for later
   312  	LEAQ	56(SP), DX				// lpDueTime
   313  	MOVQ	BX, (DX)
   314  	MOVQ	$0, R8					// lPeriod
   315  	MOVQ	$0, R9					// pfnCompletionRoutine
   316  	MOVQ	$0, AX
   317  	MOVQ	AX, 32(SP)				// lpArgToCompletionRoutine
   318  	MOVQ	AX, 40(SP)				// fResume
   319  	MOVQ	runtime·_SetWaitableTimer(SB), AX
   320  	CALL	AX
   321  
   322  	MOVQ	48(SP), CX				// handle
   323  	MOVQ	$0, DX					// alertable
   324  	MOVQ	$0, R8					// ptime
   325  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   326  	CALL	AX
   327  
   328  	MOVQ	64(SP), SP
   329  	RET
   330  
   331  // Runs on OS stack.
   332  TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
   333  	MOVQ	SP, AX
   334  	ANDQ	$~15, SP	// alignment as per Windows requirement
   335  	SUBQ	$(48), SP	// room for SP and 4 args as per Windows requirement
   336  				// plus one extra word to keep stack 16 bytes aligned
   337  	MOVQ	AX, 32(SP)
   338  	MOVQ	runtime·_SwitchToThread(SB), AX
   339  	CALL	AX
   340  	MOVQ	32(SP), SP
   341  	RET
   342  
   343  TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   344  	CMPB	runtime·useQPCTime(SB), $0
   345  	JNE	useQPC
   346  	MOVQ	$_INTERRUPT_TIME, DI
   347  	MOVQ	time_lo(DI), AX
   348  	IMULQ	$100, AX
   349  	MOVQ	AX, ret+0(FP)
   350  	RET
   351  useQPC:
   352  	JMP	runtime·nanotimeQPC(SB)
   353  	RET
   354  
   355  // func osSetupTLS(mp *m)
   356  // Setup TLS. for use by needm on Windows.
   357  TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
   358  	MOVQ	mp+0(FP), AX
   359  	LEAQ	m_tls(AX), DI
   360  	CALL	runtime·settls(SB)
   361  	RET
   362  

View as plain text