...

Text file src/runtime/sys_windows_386.s

Documentation: runtime

     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
    15TEXT runtime·getlasterror(SB),NOSPLIT,$0
    16	MOVL	0x34(FS), AX
    17	MOVL	AX, ret+0(FP)
    18	RET
    19
    20TEXT 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.
    33TEXT 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.
    63TEXT runtime·sigresume(SB),NOSPLIT,$0
    64	MOVL	DX, SP
    65	JMP	CX
    66
    67TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
    68	MOVL	argframe+0(FP), AX
    69	MOVL	$const_callbackVEH, CX
    70	JMP	sigtramp<>(SB)
    71
    72TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
    73	// is never called
    74	INT	$3
    75
    76TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
    77	MOVL	argframe+0(FP), AX
    78	MOVL	$const_callbackLastVCH, CX
    79	JMP	sigtramp<>(SB)
    80
    81TEXT 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);
   142TEXT 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);
   171TEXT 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)
   188TEXT 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
   194TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   195loop:
   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.
   214TEXT 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
   230ok:
   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
   237settls:
   238	MOVL	CX, runtime·tls_g(SB)
   239	RET

View as plain text