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

View as plain text