github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/sys_windows_386.s (about)

     1  // Copyright 2009 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  
    10  // Offsets into Thread Environment Block (pointer in FS)
    11  #define TEB_TlsSlots 0xE10
    12  #define TEB_ArbitraryPtr 0x14
    13  
    14  // void runtime·asmstdcall(void *c);
    15  TEXT runtime·asmstdcall(SB),NOSPLIT,$0
    16  	MOVL	fn+0(FP), BX
    17  
    18  	// SetLastError(0).
    19  	MOVL	$0, 0x34(FS)
    20  
    21  	// Copy args to the stack.
    22  	MOVL	SP, BP
    23  	MOVL	libcall_n(BX), CX	// words
    24  	MOVL	CX, AX
    25  	SALL	$2, AX
    26  	SUBL	AX, SP			// room for args
    27  	MOVL	SP, DI
    28  	MOVL	libcall_args(BX), SI
    29  	CLD
    30  	REP; MOVSL
    31  
    32  	// Call stdcall or cdecl function.
    33  	// DI SI BP BX are preserved, SP is not
    34  	CALL	libcall_fn(BX)
    35  	MOVL	BP, SP
    36  
    37  	// Return result.
    38  	MOVL	fn+0(FP), BX
    39  	MOVL	AX, libcall_r1(BX)
    40  	MOVL	DX, libcall_r2(BX)
    41  
    42  	// GetLastError().
    43  	MOVL	0x34(FS), AX
    44  	MOVL	AX, libcall_err(BX)
    45  
    46  	RET
    47  
    48  // faster get/set last error
    49  TEXT runtime·getlasterror(SB),NOSPLIT,$0
    50  	MOVL	0x34(FS), AX
    51  	MOVL	AX, ret+0(FP)
    52  	RET
    53  
    54  TEXT runtime·sigFetchGSafe<ABIInternal>(SB),NOSPLIT,$0
    55  	get_tls(AX)
    56  	CMPL	AX, $0
    57  	JE	2(PC)
    58  	MOVL	g(AX), AX
    59  	MOVL	AX, ret+0(FP)
    60  	RET
    61  
    62  // Called by Windows as a Vectored Exception Handler (VEH).
    63  // AX is pointer to struct containing
    64  // exception record and context pointers.
    65  // CX is the kind of sigtramp function.
    66  // Return value of sigtrampgo is stored in AX.
    67  TEXT sigtramp<>(SB),NOSPLIT,$0-0
    68  	SUBL	$40, SP
    69  
    70  	// save callee-saved registers
    71  	MOVL	BX, 28(SP)
    72  	MOVL	BP, 16(SP)
    73  	MOVL	SI, 20(SP)
    74  	MOVL	DI, 24(SP)
    75  
    76  	MOVL	AX, 0(SP)
    77  	MOVL	CX, 4(SP)
    78  	CALL	runtime·sigtrampgo(SB)
    79  	MOVL	8(SP), AX
    80  
    81  	// restore callee-saved registers
    82  	MOVL	24(SP), DI
    83  	MOVL	20(SP), SI
    84  	MOVL	16(SP), BP
    85  	MOVL	28(SP), BX
    86  
    87  	ADDL	$40, SP
    88  	// RET 4 (return and pop 4 bytes parameters)
    89  	BYTE $0xC2; WORD $4
    90  	RET // unreached; make assembler happy
    91  
    92  // Trampoline to resume execution from exception handler.
    93  // This is part of the control flow guard workaround.
    94  // It switches stacks and jumps to the continuation address.
    95  // DX and CX are set above at the end of sigtrampgo
    96  // in the context that starts executing at sigresume.
    97  TEXT runtime·sigresume(SB),NOSPLIT,$0
    98  	MOVL	DX, SP
    99  	JMP	CX
   100  
   101  TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
   102  	MOVL	argframe+0(FP), AX
   103  	MOVL	$const_callbackVEH, CX
   104  	JMP	sigtramp<>(SB)
   105  
   106  TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
   107  	// is never called
   108  	INT	$3
   109  
   110  TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
   111  	MOVL	argframe+0(FP), AX
   112  	MOVL	$const_callbackLastVCH, CX
   113  	JMP	sigtramp<>(SB)
   114  
   115  TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   116  	MOVL	0(SP), AX	// will use to find our callback context
   117  
   118  	// remove return address from stack, we are not returning to callbackasm, but to its caller.
   119  	ADDL	$4, SP
   120  
   121  	// address to callback parameters into CX
   122  	LEAL	4(SP), CX
   123  
   124  	// save registers as required for windows callback
   125  	PUSHL	DI
   126  	PUSHL	SI
   127  	PUSHL	BP
   128  	PUSHL	BX
   129  
   130  	// Go ABI requires DF flag to be cleared.
   131  	CLD
   132  
   133  	// determine index into runtime·cbs table
   134  	SUBL	$runtime·callbackasm(SB), AX
   135  	MOVL	$0, DX
   136  	MOVL	$5, BX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   137  	DIVL	BX
   138  	SUBL	$1, AX	// subtract 1 because return PC is to the next slot
   139  
   140  	// Create a struct callbackArgs on our stack.
   141  	SUBL	$(12+callbackArgs__size), SP
   142  	MOVL	AX, (12+callbackArgs_index)(SP)		// callback index
   143  	MOVL	CX, (12+callbackArgs_args)(SP)		// address of args vector
   144  	MOVL	$0, (12+callbackArgs_result)(SP)	// result
   145  	LEAL	12(SP), AX	// AX = &callbackArgs{...}
   146  
   147  	// Call cgocallback, which will call callbackWrap(frame).
   148  	MOVL	$0, 8(SP)	// context
   149  	MOVL	AX, 4(SP)	// frame (address of callbackArgs)
   150  	LEAL	·callbackWrap(SB), AX
   151  	MOVL	AX, 0(SP)	// PC of function to call
   152  	CALL	runtime·cgocallback(SB)
   153  
   154  	// Get callback result.
   155  	MOVL	(12+callbackArgs_result)(SP), AX
   156  	// Get popRet.
   157  	MOVL	(12+callbackArgs_retPop)(SP), CX	// Can't use a callee-save register
   158  	ADDL	$(12+callbackArgs__size), SP
   159  
   160  	// restore registers as required for windows callback
   161  	POPL	BX
   162  	POPL	BP
   163  	POPL	SI
   164  	POPL	DI
   165  
   166  	// remove callback parameters before return (as per Windows spec)
   167  	POPL	DX
   168  	ADDL	CX, SP
   169  	PUSHL	DX
   170  
   171  	CLD
   172  
   173  	RET
   174  
   175  // void tstart(M *newm);
   176  TEXT tstart<>(SB),NOSPLIT,$8-4
   177  	MOVL	newm+0(FP), CX		// m
   178  	MOVL	m_g0(CX), DX		// g
   179  
   180  	// Layout new m scheduler stack on os stack.
   181  	MOVL	SP, AX
   182  	MOVL	AX, (g_stack+stack_hi)(DX)
   183  	SUBL	$(64*1024), AX		// initial stack size (adjusted later)
   184  	MOVL	AX, (g_stack+stack_lo)(DX)
   185  	ADDL	$const_stackGuard, AX
   186  	MOVL	AX, g_stackguard0(DX)
   187  	MOVL	AX, g_stackguard1(DX)
   188  
   189  	// Set up tls.
   190  	LEAL	m_tls(CX), DI
   191  	MOVL	CX, g_m(DX)
   192  	MOVL	DX, g(DI)
   193  	MOVL	DI, 4(SP)
   194  	CALL	runtime·setldt(SB) // clobbers CX and DX
   195  
   196  	// Someday the convention will be D is always cleared.
   197  	CLD
   198  
   199  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   200  	CALL	runtime·mstart(SB)
   201  
   202  	RET
   203  
   204  // uint32 tstart_stdcall(M *newm);
   205  TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   206  	MOVL	newm+0(FP), BX
   207  
   208  	PUSHL	BX
   209  	CALL	tstart<>(SB)
   210  	POPL	BX
   211  
   212  	// Adjust stack for stdcall to return properly.
   213  	MOVL	(SP), AX		// save return address
   214  	ADDL	$4, SP			// remove single parameter
   215  	MOVL	AX, (SP)		// restore return address
   216  
   217  	XORL	AX, AX			// return 0 == success
   218  
   219  	RET
   220  
   221  // setldt(int slot, int base, int size)
   222  TEXT runtime·setldt(SB),NOSPLIT,$0-12
   223  	MOVL	base+4(FP), DX
   224  	MOVL	runtime·tls_g(SB), CX
   225  	MOVL	DX, 0(CX)(FS)
   226  	RET
   227  
   228  // Runs on OS stack.
   229  // duration (in -100ns units) is in dt+0(FP).
   230  // g may be nil.
   231  TEXT runtime·usleep2(SB),NOSPLIT,$20-4
   232  	MOVL	dt+0(FP), BX
   233  	MOVL	$-1, hi-4(SP)
   234  	MOVL	BX, lo-8(SP)
   235  	LEAL	lo-8(SP), BX
   236  	MOVL	BX, ptime-12(SP)
   237  	MOVL	$0, alertable-16(SP)
   238  	MOVL	$-1, handle-20(SP)
   239  	MOVL	SP, BP
   240  	MOVL	runtime·_NtWaitForSingleObject(SB), AX
   241  	CALL	AX
   242  	MOVL	BP, SP
   243  	RET
   244  
   245  // Runs on OS stack.
   246  TEXT runtime·switchtothread(SB),NOSPLIT,$0
   247  	MOVL	SP, BP
   248  	MOVL	runtime·_SwitchToThread(SB), AX
   249  	CALL	AX
   250  	MOVL	BP, SP
   251  	RET
   252  
   253  TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   254  	CMPB	runtime·useQPCTime(SB), $0
   255  	JNE	useQPC
   256  loop:
   257  	MOVL	(_INTERRUPT_TIME+time_hi1), AX
   258  	MOVL	(_INTERRUPT_TIME+time_lo), CX
   259  	MOVL	(_INTERRUPT_TIME+time_hi2), DI
   260  	CMPL	AX, DI
   261  	JNE	loop
   262  
   263  	// wintime = DI:CX, multiply by 100
   264  	MOVL	$100, AX
   265  	MULL	CX
   266  	IMULL	$100, DI
   267  	ADDL	DI, DX
   268  	// wintime*100 = DX:AX
   269  	MOVL	AX, ret_lo+0(FP)
   270  	MOVL	DX, ret_hi+4(FP)
   271  	RET
   272  useQPC:
   273  	JMP	runtime·nanotimeQPC(SB)
   274  	RET
   275  
   276  // This is called from rt0_go, which runs on the system stack
   277  // using the initial stack allocated by the OS.
   278  TEXT runtime·wintls(SB),NOSPLIT,$0
   279  	// Allocate a TLS slot to hold g across calls to external code
   280  	MOVL	SP, BP
   281  	MOVL	runtime·_TlsAlloc(SB), AX
   282  	CALL	AX
   283  	MOVL	BP, SP
   284  
   285  	MOVL	AX, CX	// TLS index
   286  
   287  	// Assert that slot is less than 64 so we can use _TEB->TlsSlots
   288  	CMPL	CX, $64
   289  	JB	ok
   290  	// Fallback to the TEB arbitrary pointer.
   291  	// TODO: don't use the arbitrary pointer (see go.dev/issue/59824)
   292  	MOVL	$TEB_ArbitraryPtr, CX
   293  	JMP	settls
   294  ok:
   295  	// Convert the TLS index at CX into
   296  	// an offset from TEB_TlsSlots.
   297  	SHLL	$2, CX
   298  
   299  	// Save offset from TLS into tls_g.
   300  	ADDL	$TEB_TlsSlots, CX
   301  settls:
   302  	MOVL	CX, runtime·tls_g(SB)
   303  	RET