Text file src/runtime/sys_windows_386.s

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

View as plain text