github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/sys_windows_amd64.s (about)

     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  
     9  // maxargs should be divisible by 2, as Windows stack
    10  // must be kept 16-byte aligned on syscall entry.
    11  #define maxargs 16
    12  
    13  // void runtime·asmstdcall(void *c);
    14  TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
    15  	// asmcgocall will put first argument into CX.
    16  	PUSHQ	CX			// save for later
    17  	MOVQ	libcall_fn(CX), AX
    18  	MOVQ	libcall_args(CX), SI
    19  	MOVQ	libcall_n(CX), CX
    20  
    21  	// SetLastError(0).
    22  	MOVQ	0x30(GS), DI
    23  	MOVL	$0, 0x68(DI)
    24  
    25  	SUBQ	$(maxargs*8), SP	// room for args
    26  
    27  	// Fast version, do not store args on the stack.
    28  	CMPL	CX, $4
    29  	JLE	loadregs
    30  
    31  	// Check we have enough room for args.
    32  	CMPL	CX, $maxargs
    33  	JLE	2(PC)
    34  	INT	$3			// not enough room -> crash
    35  
    36  	// Copy args to the stack.
    37  	MOVQ	SP, DI
    38  	CLD
    39  	REP; MOVSQ
    40  	MOVQ	SP, SI
    41  
    42  loadregs:
    43  	// Load first 4 args into correspondent registers.
    44  	MOVQ	0(SI), CX
    45  	MOVQ	8(SI), DX
    46  	MOVQ	16(SI), R8
    47  	MOVQ	24(SI), R9
    48  	// Floating point arguments are passed in the XMM
    49  	// registers. Set them here in case any of the arguments
    50  	// are floating point values. For details see
    51  	//	https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
    52  	MOVQ	CX, X0
    53  	MOVQ	DX, X1
    54  	MOVQ	R8, X2
    55  	MOVQ	R9, X3
    56  
    57  	// Call stdcall function.
    58  	CALL	AX
    59  
    60  	ADDQ	$(maxargs*8), SP
    61  
    62  	// Return result.
    63  	POPQ	CX
    64  	MOVQ	AX, libcall_r1(CX)
    65  	// Floating point return values are returned in XMM0. Setting r2 to this
    66  	// value in case this call returned a floating point value. For details,
    67  	// see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
    68  	MOVQ    X0, libcall_r2(CX)
    69  
    70  	// GetLastError().
    71  	MOVQ	0x30(GS), DI
    72  	MOVL	0x68(DI), AX
    73  	MOVQ	AX, libcall_err(CX)
    74  
    75  	RET
    76  
    77  TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48
    78  	// stderr
    79  	MOVQ	$-12, CX // stderr
    80  	MOVQ	CX, 0(SP)
    81  	MOVQ	runtime·_GetStdHandle(SB), AX
    82  	CALL	AX
    83  
    84  	MOVQ	AX, CX	// handle
    85  	MOVQ	CX, 0(SP)
    86  	MOVQ	$runtime·badsignalmsg(SB), DX // pointer
    87  	MOVQ	DX, 8(SP)
    88  	MOVL	$runtime·badsignallen(SB), R8 // count
    89  	MOVQ	R8, 16(SP)
    90  	LEAQ	40(SP), R9  // written count
    91  	MOVQ	$0, 0(R9)
    92  	MOVQ	R9, 24(SP)
    93  	MOVQ	$0, 32(SP)	// overlapped
    94  	MOVQ	runtime·_WriteFile(SB), AX
    95  	CALL	AX
    96  
    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  TEXT runtime·setlasterror(SB),NOSPLIT,$0
   107  	MOVL	err+0(FP), AX
   108  	MOVQ	0x30(GS),	CX
   109  	MOVL	AX, 0x68(CX)
   110  	RET
   111  
   112  // Called by Windows as a Vectored Exception Handler (VEH).
   113  // First argument is pointer to struct containing
   114  // exception record and context pointers.
   115  // Handler function is stored in AX.
   116  // Return 0 for 'not handled', -1 for handled.
   117  TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
   118  	// CX: PEXCEPTION_POINTERS ExceptionInfo
   119  
   120  	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
   121  	// as required by windows callback convention.
   122  	PUSHFQ
   123  	SUBQ	$112, SP
   124  	MOVQ	DI, 80(SP)
   125  	MOVQ	SI, 72(SP)
   126  	MOVQ	BP, 64(SP)
   127  	MOVQ	BX, 56(SP)
   128  	MOVQ	R12, 48(SP)
   129  	MOVQ	R13, 40(SP)
   130  	MOVQ	R14, 32(SP)
   131  	MOVQ	R15, 88(SP)
   132  
   133  	MOVQ	AX, R15	// save handler address
   134  
   135  	// find g
   136  	get_tls(DX)
   137  	CMPQ	DX, $0
   138  	JNE	3(PC)
   139  	MOVQ	$0, AX // continue
   140  	JMP	done
   141  	MOVQ	g(DX), DX
   142  	CMPQ	DX, $0
   143  	JNE	2(PC)
   144  	CALL	runtime·badsignal2(SB)
   145  
   146  	// save g and SP in case of stack switch
   147  	MOVQ	DX, 96(SP) // g
   148  	MOVQ	SP, 104(SP)
   149  
   150  	// do we need to switch to the g0 stack?
   151  	MOVQ	g_m(DX), BX
   152  	MOVQ	m_g0(BX), BX
   153  	CMPQ	DX, BX
   154  	JEQ	g0
   155  
   156  	// switch to g0 stack
   157  	get_tls(BP)
   158  	MOVQ	BX, g(BP)
   159  	MOVQ	(g_sched+gobuf_sp)(BX), DI
   160  	// make it look like mstart called us on g0, to stop traceback
   161  	SUBQ	$8, DI
   162  	MOVQ	$runtime·mstart(SB), SI
   163  	MOVQ	SI, 0(DI)
   164  	// traceback will think that we've done PUSHFQ and SUBQ
   165  	// on this stack, so subtract them here to match.
   166  	// (we need room for sighandler arguments anyway).
   167  	// and re-save old SP for restoring later.
   168  	SUBQ	$(112+8), DI
   169  	// save g, save old stack pointer.
   170  	MOVQ	SP, 104(DI)
   171  	MOVQ	DI, SP
   172  
   173  g0:
   174  	MOVQ	0(CX), BX // ExceptionRecord*
   175  	MOVQ	8(CX), CX // Context*
   176  	MOVQ	BX, 0(SP)
   177  	MOVQ	CX, 8(SP)
   178  	MOVQ	DX, 16(SP)
   179  	CALL	R15	// call handler
   180  	// AX is set to report result back to Windows
   181  	MOVL	24(SP), AX
   182  
   183  	// switch back to original stack and g
   184  	// no-op if we never left.
   185  	MOVQ	104(SP), SP
   186  	MOVQ	96(SP), DX
   187  	get_tls(BP)
   188  	MOVQ	DX, g(BP)
   189  
   190  done:
   191  	// restore registers as required for windows callback
   192  	MOVQ	88(SP), R15
   193  	MOVQ	32(SP), R14
   194  	MOVQ	40(SP), R13
   195  	MOVQ	48(SP), R12
   196  	MOVQ	56(SP), BX
   197  	MOVQ	64(SP), BP
   198  	MOVQ	72(SP), SI
   199  	MOVQ	80(SP), DI
   200  	ADDQ	$112, SP
   201  	POPFQ
   202  
   203  	RET
   204  
   205  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   206  	MOVQ	$runtime·exceptionhandler(SB), AX
   207  	JMP	sigtramp<>(SB)
   208  
   209  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   210  	MOVQ	$runtime·firstcontinuehandler(SB), AX
   211  	JMP	sigtramp<>(SB)
   212  
   213  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0
   214  	MOVQ	$runtime·lastcontinuehandler(SB), AX
   215  	JMP	sigtramp<>(SB)
   216  
   217  TEXT runtime·ctrlhandler(SB),NOSPLIT|NOFRAME,$8
   218  	MOVQ	CX, 16(SP)		// spill
   219  	MOVQ	$runtime·ctrlhandler1(SB), CX
   220  	MOVQ	CX, 0(SP)
   221  	CALL	runtime·externalthreadhandler(SB)
   222  	RET
   223  
   224  TEXT runtime·profileloop(SB),NOSPLIT|NOFRAME,$8
   225  	MOVQ	$runtime·profileloop1(SB), CX
   226  	MOVQ	CX, 0(SP)
   227  	CALL	runtime·externalthreadhandler(SB)
   228  	RET
   229  
   230  TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
   231  	PUSHQ	BP
   232  	MOVQ	SP, BP
   233  	PUSHQ	BX
   234  	PUSHQ	SI
   235  	PUSHQ	DI
   236  	PUSHQ	0x28(GS)
   237  	MOVQ	SP, DX
   238  
   239  	// setup dummy m, g
   240  	SUBQ	$m__size, SP		// space for M
   241  	MOVQ	SP, 0(SP)
   242  	MOVQ	$m__size, 8(SP)
   243  	CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX, maybe BP
   244  
   245  	LEAQ	m_tls(SP), CX
   246  	MOVQ	CX, 0x28(GS)
   247  	MOVQ	SP, BX
   248  	SUBQ	$g__size, SP		// space for G
   249  	MOVQ	SP, g(CX)
   250  	MOVQ	SP, m_g0(BX)
   251  
   252  	MOVQ	SP, 0(SP)
   253  	MOVQ	$g__size, 8(SP)
   254  	CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX, maybe BP
   255  	LEAQ	g__size(SP), BX
   256  	MOVQ	BX, g_m(SP)
   257  
   258  	LEAQ	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
   259  	MOVQ	CX, (g_stack+stack_lo)(SP)
   260  	ADDQ	$const__StackGuard, CX
   261  	MOVQ	CX, g_stackguard0(SP)
   262  	MOVQ	CX, g_stackguard1(SP)
   263  	MOVQ	DX, (g_stack+stack_hi)(SP)
   264  
   265  	PUSHQ	AX			// room for return value
   266  	PUSHQ	32(BP)			// arg for handler
   267  	CALL	16(BP)
   268  	POPQ	CX
   269  	POPQ	AX			// pass return value to Windows in AX
   270  
   271  	get_tls(CX)
   272  	MOVQ	g(CX), CX
   273  	MOVQ	(g_stack+stack_hi)(CX), SP
   274  	POPQ	0x28(GS)
   275  	POPQ	DI
   276  	POPQ	SI
   277  	POPQ	BX
   278  	POPQ	BP
   279  	RET
   280  
   281  GLOBL runtime·cbctxts(SB), NOPTR, $8
   282  
   283  TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   284  	// Construct args vector for cgocallback().
   285  	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
   286  	// args from the 5th on are on the stack.
   287  	// In any case, even if function has 0,1,2,3,4 args, there is reserved
   288  	// but uninitialized "shadow space" for the first 4 args.
   289  	// The values are in registers.
   290    	MOVQ	CX, (16+0)(SP)
   291    	MOVQ	DX, (16+8)(SP)
   292    	MOVQ	R8, (16+16)(SP)
   293    	MOVQ	R9, (16+24)(SP)
   294  	// R8 = address of args vector
   295  	LEAQ	(16+0)(SP), R8
   296  
   297  	// remove return address from stack, we are not returning to callbackasm, but to its caller.
   298    	MOVQ	0(SP), AX
   299  	ADDQ	$8, SP
   300  
   301  	// determine index into runtime·cbs table
   302  	MOVQ	$runtime·callbackasm(SB), DX
   303  	SUBQ	DX, AX
   304  	MOVQ	$0, DX
   305  	MOVQ	$5, CX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   306  	DIVL	CX
   307  	SUBQ	$1, AX	// subtract 1 because return PC is to the next slot
   308  
   309  	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
   310  	// as required by windows callback convention.
   311  	PUSHFQ
   312  	SUBQ	$64, SP
   313  	MOVQ	DI, 56(SP)
   314  	MOVQ	SI, 48(SP)
   315  	MOVQ	BP, 40(SP)
   316  	MOVQ	BX, 32(SP)
   317  	MOVQ	R12, 24(SP)
   318  	MOVQ	R13, 16(SP)
   319  	MOVQ	R14, 8(SP)
   320  	MOVQ	R15, 0(SP)
   321  
   322  	// Go ABI requires DF flag to be cleared.
   323  	CLD
   324  
   325  	// Create a struct callbackArgs on our stack to be passed as
   326  	// the "frame" to cgocallback and on to callbackWrap.
   327  	SUBQ	$(24+callbackArgs__size), SP
   328  	MOVQ	AX, (24+callbackArgs_index)(SP) 	// callback index
   329  	MOVQ	R8, (24+callbackArgs_args)(SP)  	// address of args vector
   330  	MOVQ	$0, (24+callbackArgs_result)(SP)	// result
   331  	LEAQ	24(SP), AX
   332  	// Call cgocallback, which will call callbackWrap(frame).
   333  	MOVQ	$0, 16(SP)	// context
   334  	MOVQ	AX, 8(SP)	// frame (address of callbackArgs)
   335  	LEAQ	·callbackWrap(SB), BX
   336  	MOVQ	BX, 0(SP)	// PC of function value to call (callbackWrap)
   337  	CALL	·cgocallback(SB)
   338  	// Get callback result.
   339  	MOVQ	(24+callbackArgs_result)(SP), AX
   340  	ADDQ	$(24+callbackArgs__size), SP
   341  
   342  	// restore registers as required for windows callback
   343  	MOVQ	0(SP), R15
   344  	MOVQ	8(SP), R14
   345  	MOVQ	16(SP), R13
   346  	MOVQ	24(SP), R12
   347  	MOVQ	32(SP), BX
   348  	MOVQ	40(SP), BP
   349  	MOVQ	48(SP), SI
   350  	MOVQ	56(SP), DI
   351  	ADDQ	$64, SP
   352  	POPFQ
   353  
   354  	// The return value was placed in AX above.
   355  	RET
   356  
   357  // uint32 tstart_stdcall(M *newm);
   358  TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   359  	// CX contains first arg newm
   360  	MOVQ	m_g0(CX), DX		// g
   361  
   362  	// Layout new m scheduler stack on os stack.
   363  	MOVQ	SP, AX
   364  	MOVQ	AX, (g_stack+stack_hi)(DX)
   365  	SUBQ	$(64*1024), AX		// initial stack size (adjusted later)
   366  	MOVQ	AX, (g_stack+stack_lo)(DX)
   367  	ADDQ	$const__StackGuard, AX
   368  	MOVQ	AX, g_stackguard0(DX)
   369  	MOVQ	AX, g_stackguard1(DX)
   370  
   371  	// Set up tls.
   372  	LEAQ	m_tls(CX), SI
   373  	MOVQ	SI, 0x28(GS)
   374  	MOVQ	CX, g_m(DX)
   375  	MOVQ	DX, g(SI)
   376  
   377  	// Someday the convention will be D is always cleared.
   378  	CLD
   379  
   380  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   381  	CALL	runtime·mstart(SB)
   382  
   383  	XORL	AX, AX			// return 0 == success
   384  	RET
   385  
   386  // set tls base to DI
   387  TEXT runtime·settls(SB),NOSPLIT,$0
   388  	MOVQ	DI, 0x28(GS)
   389  	RET
   390  
   391  // func onosstack(fn unsafe.Pointer, arg uint32)
   392  TEXT runtime·onosstack(SB),NOSPLIT,$0
   393  	MOVQ	fn+0(FP), AX		// to hide from 6l
   394  	MOVL	arg+8(FP), BX
   395  
   396  	// Execute call on m->g0 stack, in case we are not actually
   397  	// calling a system call wrapper, like when running under WINE.
   398  	get_tls(R15)
   399  	CMPQ	R15, $0
   400  	JNE	3(PC)
   401  	// Not a Go-managed thread. Do not switch stack.
   402  	CALL	AX
   403  	RET
   404  
   405  	MOVQ	g(R15), R13
   406  	MOVQ	g_m(R13), R13
   407  
   408  	// leave pc/sp for cpu profiler
   409  	MOVQ	(SP), R12
   410  	MOVQ	R12, m_libcallpc(R13)
   411  	MOVQ	g(R15), R12
   412  	MOVQ	R12, m_libcallg(R13)
   413  	// sp must be the last, because once async cpu profiler finds
   414  	// all three values to be non-zero, it will use them
   415  	LEAQ	fn+0(FP), R12
   416  	MOVQ	R12, m_libcallsp(R13)
   417  
   418  	MOVQ	m_g0(R13), R14
   419  	CMPQ	g(R15), R14
   420  	JNE	switch
   421  	// executing on m->g0 already
   422  	CALL	AX
   423  	JMP	ret
   424  
   425  switch:
   426  	// Switch to m->g0 stack and back.
   427  	MOVQ	(g_sched+gobuf_sp)(R14), R14
   428  	MOVQ	SP, -8(R14)
   429  	LEAQ	-8(R14), SP
   430  	CALL	AX
   431  	MOVQ	0(SP), SP
   432  
   433  ret:
   434  	MOVQ	$0, m_libcallsp(R13)
   435  	RET
   436  
   437  // Runs on OS stack. duration (in 100ns units) is in BX.
   438  // The function leaves room for 4 syscall parameters
   439  // (as per windows amd64 calling convention).
   440  TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48
   441  	MOVQ	SP, AX
   442  	ANDQ	$~15, SP	// alignment as per Windows requirement
   443  	MOVQ	AX, 40(SP)
   444  	// Want negative 100ns units.
   445  	NEGQ	BX
   446  	LEAQ	32(SP), R8  // ptime
   447  	MOVQ	BX, (R8)
   448  	MOVQ	$-1, CX // handle
   449  	MOVQ	$0, DX // alertable
   450  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   451  	CALL	AX
   452  	MOVQ	40(SP), SP
   453  	RET
   454  
   455  // Runs on OS stack. duration (in 100ns units) is in BX.
   456  TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72
   457  	get_tls(CX)
   458  	CMPQ	CX, $0
   459  	JE	gisnotset
   460  
   461  	MOVQ	SP, AX
   462  	ANDQ	$~15, SP	// alignment as per Windows requirement
   463  	MOVQ	AX, 64(SP)
   464  
   465  	MOVQ	g(CX), CX
   466  	MOVQ	g_m(CX), CX
   467  	MOVQ	(m_mOS+mOS_highResTimer)(CX), CX	// hTimer
   468  	MOVQ	CX, 48(SP)				// save hTimer for later
   469  	// Want negative 100ns units.
   470  	NEGQ	BX
   471  	LEAQ	56(SP), DX				// lpDueTime
   472  	MOVQ	BX, (DX)
   473  	MOVQ	$0, R8					// lPeriod
   474  	MOVQ	$0, R9					// pfnCompletionRoutine
   475  	MOVQ	$0, AX
   476  	MOVQ	AX, 32(SP)				// lpArgToCompletionRoutine
   477  	MOVQ	AX, 40(SP)				// fResume
   478  	MOVQ	runtime·_SetWaitableTimer(SB), AX
   479  	CALL	AX
   480  
   481  	MOVQ	48(SP), CX				// handle
   482  	MOVQ	$0, DX					// alertable
   483  	MOVQ	$0, R8					// ptime
   484  	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
   485  	CALL	AX
   486  
   487  	MOVQ	64(SP), SP
   488  	RET
   489  
   490  gisnotset:
   491  	// TLS is not configured. Call usleep2 instead.
   492  	MOVQ	$runtime·usleep2(SB), AX
   493  	CALL	AX
   494  	RET
   495  
   496  // Runs on OS stack.
   497  TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
   498  	MOVQ	SP, AX
   499  	ANDQ	$~15, SP	// alignment as per Windows requirement
   500  	SUBQ	$(48), SP	// room for SP and 4 args as per Windows requirement
   501  				// plus one extra word to keep stack 16 bytes aligned
   502  	MOVQ	AX, 32(SP)
   503  	MOVQ	runtime·_SwitchToThread(SB), AX
   504  	CALL	AX
   505  	MOVQ	32(SP), SP
   506  	RET
   507  
   508  // See https://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
   509  // Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2.
   510  #define _INTERRUPT_TIME 0x7ffe0008
   511  #define _SYSTEM_TIME 0x7ffe0014
   512  #define time_lo 0
   513  #define time_hi1 4
   514  #define time_hi2 8
   515  
   516  TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   517  	CMPB	runtime·useQPCTime(SB), $0
   518  	JNE	useQPC
   519  	MOVQ	$_INTERRUPT_TIME, DI
   520  loop:
   521  	MOVL	time_hi1(DI), AX
   522  	MOVL	time_lo(DI), BX
   523  	MOVL	time_hi2(DI), CX
   524  	CMPL	AX, CX
   525  	JNE	loop
   526  	SHLQ	$32, CX
   527  	ORQ	BX, CX
   528  	IMULQ	$100, CX
   529  	MOVQ	CX, ret+0(FP)
   530  	RET
   531  useQPC:
   532  	JMP	runtime·nanotimeQPC(SB)
   533  	RET
   534  
   535  TEXT time·now(SB),NOSPLIT,$0-24
   536  	CMPB	runtime·useQPCTime(SB), $0
   537  	JNE	useQPC
   538  	MOVQ	$_INTERRUPT_TIME, DI
   539  loop:
   540  	MOVL	time_hi1(DI), AX
   541  	MOVL	time_lo(DI), BX
   542  	MOVL	time_hi2(DI), CX
   543  	CMPL	AX, CX
   544  	JNE	loop
   545  	SHLQ	$32, AX
   546  	ORQ	BX, AX
   547  	IMULQ	$100, AX
   548  	MOVQ	AX, mono+16(FP)
   549  
   550  	MOVQ	$_SYSTEM_TIME, DI
   551  wall:
   552  	MOVL	time_hi1(DI), AX
   553  	MOVL	time_lo(DI), BX
   554  	MOVL	time_hi2(DI), CX
   555  	CMPL	AX, CX
   556  	JNE	wall
   557  	SHLQ	$32, AX
   558  	ORQ	BX, AX
   559  	MOVQ	$116444736000000000, DI
   560  	SUBQ	DI, AX
   561  	IMULQ	$100, AX
   562  
   563  	// generated code for
   564  	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
   565  	// adapted to reduce duplication
   566  	MOVQ	AX, CX
   567  	MOVQ	$1360296554856532783, AX
   568  	MULQ	CX
   569  	ADDQ	CX, DX
   570  	RCRQ	$1, DX
   571  	SHRQ	$29, DX
   572  	MOVQ	DX, sec+0(FP)
   573  	IMULQ	$1000000000, DX
   574  	SUBQ	DX, CX
   575  	MOVL	CX, nsec+8(FP)
   576  	RET
   577  useQPC:
   578  	JMP	runtime·nowQPC(SB)
   579  	RET