...

Text file src/pkg/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	
     9	// void runtime·asmstdcall(void *c);
    10	TEXT runtime·asmstdcall(SB),NOSPLIT,$0
    11		MOVL	fn+0(FP), BX
    12	
    13		// SetLastError(0).
    14		MOVL	$0, 0x34(FS)
    15	
    16		// Copy args to the stack.
    17		MOVL	SP, BP
    18		MOVL	libcall_n(BX), CX	// words
    19		MOVL	CX, AX
    20		SALL	$2, AX
    21		SUBL	AX, SP			// room for args
    22		MOVL	SP, DI
    23		MOVL	libcall_args(BX), SI
    24		CLD
    25		REP; MOVSL
    26	
    27		// Call stdcall or cdecl function.
    28		// DI SI BP BX are preserved, SP is not
    29		CALL	libcall_fn(BX)
    30		MOVL	BP, SP
    31	
    32		// Return result.
    33		MOVL	fn+0(FP), BX
    34		MOVL	AX, libcall_r1(BX)
    35		MOVL	DX, libcall_r2(BX)
    36	
    37		// GetLastError().
    38		MOVL	0x34(FS), AX
    39		MOVL	AX, libcall_err(BX)
    40	
    41		RET
    42	
    43	TEXT	runtime·badsignal2(SB),NOSPLIT,$24
    44		// stderr
    45		MOVL	$-12, 0(SP)
    46		MOVL	SP, BP
    47		CALL	*runtime·_GetStdHandle(SB)
    48		MOVL	BP, SP
    49	
    50		MOVL	AX, 0(SP)	// handle
    51		MOVL	$runtime·badsignalmsg(SB), DX // pointer
    52		MOVL	DX, 4(SP)
    53		MOVL	runtime·badsignallen(SB), DX // count
    54		MOVL	DX, 8(SP)
    55		LEAL	20(SP), DX  // written count
    56		MOVL	$0, 0(DX)
    57		MOVL	DX, 12(SP)
    58		MOVL	$0, 16(SP) // overlapped
    59		CALL	*runtime·_WriteFile(SB)
    60		MOVL	BP, SI
    61		RET
    62	
    63	// faster get/set last error
    64	TEXT runtime·getlasterror(SB),NOSPLIT,$0
    65		MOVL	0x34(FS), AX
    66		MOVL	AX, ret+0(FP)
    67		RET
    68	
    69	TEXT runtime·setlasterror(SB),NOSPLIT,$0
    70		MOVL	err+0(FP), AX
    71		MOVL	AX, 0x34(FS)
    72		RET
    73	
    74	// Called by Windows as a Vectored Exception Handler (VEH).
    75	// First argument is pointer to struct containing
    76	// exception record and context pointers.
    77	// Handler function is stored in AX.
    78	// Return 0 for 'not handled', -1 for handled.
    79	TEXT sigtramp<>(SB),NOSPLIT,$0-0
    80		MOVL	ptrs+0(FP), CX
    81		SUBL	$40, SP
    82	
    83		// save callee-saved registers
    84		MOVL	BX, 28(SP)
    85		MOVL	BP, 16(SP)
    86		MOVL	SI, 20(SP)
    87		MOVL	DI, 24(SP)
    88	
    89		MOVL	AX, SI	// save handler address
    90	
    91		// find g
    92		get_tls(DX)
    93		CMPL	DX, $0
    94		JNE	3(PC)
    95		MOVL	$0, AX // continue
    96		JMP	done
    97		MOVL	g(DX), DX
    98		CMPL	DX, $0
    99		JNE	2(PC)
   100		CALL	runtime·badsignal2(SB)
   101	
   102		// save g and SP in case of stack switch
   103		MOVL	DX, 32(SP)	// g
   104		MOVL	SP, 36(SP)
   105	
   106		// do we need to switch to the g0 stack?
   107		MOVL	g_m(DX), BX
   108		MOVL	m_g0(BX), BX
   109		CMPL	DX, BX
   110		JEQ	g0
   111	
   112		// switch to the g0 stack
   113		get_tls(BP)
   114		MOVL	BX, g(BP)
   115		MOVL	(g_sched+gobuf_sp)(BX), DI
   116		// make it look like mstart called us on g0, to stop traceback
   117		SUBL	$4, DI
   118		MOVL	$runtime·mstart(SB), 0(DI)
   119		// traceback will think that we've done SUBL
   120		// on this stack, so subtract them here to match.
   121		// (we need room for sighandler arguments anyway).
   122		// and re-save old SP for restoring later.
   123		SUBL	$40, DI
   124		MOVL	SP, 36(DI)
   125		MOVL	DI, SP
   126	
   127	g0:
   128		MOVL	0(CX), BX // ExceptionRecord*
   129		MOVL	4(CX), CX // Context*
   130		MOVL	BX, 0(SP)
   131		MOVL	CX, 4(SP)
   132		MOVL	DX, 8(SP)
   133		CALL	SI	// call handler
   134		// AX is set to report result back to Windows
   135		MOVL	12(SP), AX
   136	
   137		// switch back to original stack and g
   138		// no-op if we never left.
   139		MOVL	36(SP), SP
   140		MOVL	32(SP), DX
   141		get_tls(BP)
   142		MOVL	DX, g(BP)
   143	
   144	done:
   145		// restore callee-saved registers
   146		MOVL	24(SP), DI
   147		MOVL	20(SP), SI
   148		MOVL	16(SP), BP
   149		MOVL	28(SP), BX
   150	
   151		ADDL	$40, SP
   152		// RET 4 (return and pop 4 bytes parameters)
   153		BYTE $0xC2; WORD $4
   154		RET // unreached; make assembler happy
   155	
   156	TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
   157		MOVL	$runtime·exceptionhandler(SB), AX
   158		JMP	sigtramp<>(SB)
   159	
   160	TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
   161		// is never called
   162		INT	$3
   163	
   164	TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
   165		MOVL	$runtime·lastcontinuehandler(SB), AX
   166		JMP	sigtramp<>(SB)
   167	
   168	// Called by OS using stdcall ABI: bool ctrlhandler(uint32).
   169	TEXT runtime·ctrlhandler(SB),NOSPLIT,$0
   170		PUSHL	$runtime·ctrlhandler1(SB)
   171		NOP	SP	// tell vet SP changed - stop checking offsets
   172		CALL	runtime·externalthreadhandler(SB)
   173		MOVL	4(SP), CX
   174		ADDL	$12, SP
   175		JMP	CX
   176	
   177	// Called by OS using stdcall ABI: uint32 profileloop(void*).
   178	TEXT runtime·profileloop(SB),NOSPLIT,$0
   179		PUSHL	$runtime·profileloop1(SB)
   180		NOP	SP	// tell vet SP changed - stop checking offsets
   181		CALL	runtime·externalthreadhandler(SB)
   182		MOVL	4(SP), CX
   183		ADDL	$12, SP
   184		JMP	CX
   185	
   186	TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
   187		PUSHL	BP
   188		MOVL	SP, BP
   189		PUSHL	BX
   190		PUSHL	SI
   191		PUSHL	DI
   192		PUSHL	0x14(FS)
   193		MOVL	SP, DX
   194	
   195		// setup dummy m, g
   196		SUBL	$m__size, SP		// space for M
   197		MOVL	SP, 0(SP)
   198		MOVL	$m__size, 4(SP)
   199		CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX
   200	
   201		LEAL	m_tls(SP), CX
   202		MOVL	CX, 0x14(FS)
   203		MOVL	SP, BX
   204		SUBL	$g__size, SP		// space for G
   205		MOVL	SP, g(CX)
   206		MOVL	SP, m_g0(BX)
   207	
   208		MOVL	SP, 0(SP)
   209		MOVL	$g__size, 4(SP)
   210		CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX
   211		LEAL	g__size(SP), BX
   212		MOVL	BX, g_m(SP)
   213	
   214		LEAL	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
   215		MOVL	CX, (g_stack+stack_lo)(SP)
   216		ADDL	$const__StackGuard, CX
   217		MOVL	CX, g_stackguard0(SP)
   218		MOVL	CX, g_stackguard1(SP)
   219		MOVL	DX, (g_stack+stack_hi)(SP)
   220	
   221		PUSHL	AX			// room for return value
   222		PUSHL	16(BP)			// arg for handler
   223		CALL	8(BP)
   224		POPL	CX
   225		POPL	AX			// pass return value to Windows in AX
   226	
   227		get_tls(CX)
   228		MOVL	g(CX), CX
   229		MOVL	(g_stack+stack_hi)(CX), SP
   230		POPL	0x14(FS)
   231		POPL	DI
   232		POPL	SI
   233		POPL	BX
   234		POPL	BP
   235		RET
   236	
   237	GLOBL runtime·cbctxts(SB), NOPTR, $4
   238	
   239	TEXT runtime·callbackasm1(SB),NOSPLIT,$0
   240	  	MOVL	0(SP), AX	// will use to find our callback context
   241	
   242		// remove return address from stack, we are not returning there
   243		ADDL	$4, SP
   244	
   245		// address to callback parameters into CX
   246		LEAL	4(SP), CX
   247	
   248		// save registers as required for windows callback
   249		PUSHL	DI
   250		PUSHL	SI
   251		PUSHL	BP
   252		PUSHL	BX
   253	
   254		// determine index into runtime·cbctxts table
   255		SUBL	$runtime·callbackasm(SB), AX
   256		MOVL	$0, DX
   257		MOVL	$5, BX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   258		DIVL	BX
   259	
   260		// find correspondent runtime·cbctxts table entry
   261		MOVL	runtime·cbctxts(SB), BX
   262		MOVL	-4(BX)(AX*4), BX
   263	
   264		// extract callback context
   265		MOVL	wincallbackcontext_gobody(BX), AX
   266		MOVL	wincallbackcontext_argsize(BX), DX
   267	
   268		// preserve whatever's at the memory location that
   269		// the callback will use to store the return value
   270		PUSHL	0(CX)(DX*1)
   271	
   272		// extend argsize by size of return value
   273		ADDL	$4, DX
   274	
   275		// remember how to restore stack on return
   276		MOVL	wincallbackcontext_restorestack(BX), BX
   277		PUSHL	BX
   278	
   279		// call target Go function
   280		PUSHL	DX			// argsize (including return value)
   281		PUSHL	CX			// callback parameters
   282		PUSHL	AX			// address of target Go function
   283		CLD
   284		CALL	runtime·cgocallback_gofunc(SB)
   285		POPL	AX
   286		POPL	CX
   287		POPL	DX
   288	
   289		// how to restore stack on return
   290		POPL	BX
   291	
   292		// return value into AX (as per Windows spec)
   293		// and restore previously preserved value
   294		MOVL	-4(CX)(DX*1), AX
   295		POPL	-4(CX)(DX*1)
   296	
   297		MOVL	BX, CX			// cannot use BX anymore
   298	
   299		// restore registers as required for windows callback
   300		POPL	BX
   301		POPL	BP
   302		POPL	SI
   303		POPL	DI
   304	
   305		// remove callback parameters before return (as per Windows spec)
   306		POPL	DX
   307		ADDL	CX, SP
   308		PUSHL	DX
   309	
   310		CLD
   311	
   312		RET
   313	
   314	// void tstart(M *newm);
   315	TEXT tstart<>(SB),NOSPLIT,$0
   316		MOVL	newm+0(FP), CX		// m
   317		MOVL	m_g0(CX), DX		// g
   318	
   319		// Layout new m scheduler stack on os stack.
   320		MOVL	SP, AX
   321		MOVL	AX, (g_stack+stack_hi)(DX)
   322		SUBL	$(64*1024), AX		// initial stack size (adjusted later)
   323		MOVL	AX, (g_stack+stack_lo)(DX)
   324		ADDL	$const__StackGuard, AX
   325		MOVL	AX, g_stackguard0(DX)
   326		MOVL	AX, g_stackguard1(DX)
   327	
   328		// Set up tls.
   329		LEAL	m_tls(CX), SI
   330		MOVL	SI, 0x14(FS)
   331		MOVL	CX, g_m(DX)
   332		MOVL	DX, g(SI)
   333	
   334		// Someday the convention will be D is always cleared.
   335		CLD
   336	
   337		CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   338		CALL	runtime·mstart(SB)
   339	
   340		RET
   341	
   342	// uint32 tstart_stdcall(M *newm);
   343	TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   344		MOVL	newm+0(FP), BX
   345	
   346		PUSHL	BX
   347		CALL	tstart<>(SB)
   348		POPL	BX
   349	
   350		// Adjust stack for stdcall to return properly.
   351		MOVL	(SP), AX		// save return address
   352		ADDL	$4, SP			// remove single parameter
   353		MOVL	AX, (SP)		// restore return address
   354	
   355		XORL	AX, AX			// return 0 == success
   356	
   357		RET
   358	
   359	// setldt(int entry, int address, int limit)
   360	TEXT runtime·setldt(SB),NOSPLIT,$0
   361		MOVL	base+4(FP), CX
   362		MOVL	CX, 0x14(FS)
   363		RET
   364	
   365	// onosstack calls fn on OS stack.
   366	// func onosstack(fn unsafe.Pointer, arg uint32)
   367	TEXT runtime·onosstack(SB),NOSPLIT,$0
   368		MOVL	fn+0(FP), AX		// to hide from 8l
   369		MOVL	arg+4(FP), BX
   370	
   371		// Execute call on m->g0 stack, in case we are not actually
   372		// calling a system call wrapper, like when running under WINE.
   373		get_tls(CX)
   374		CMPL	CX, $0
   375		JNE	3(PC)
   376		// Not a Go-managed thread. Do not switch stack.
   377		CALL	AX
   378		RET
   379	
   380		MOVL	g(CX), BP
   381		MOVL	g_m(BP), BP
   382	
   383		// leave pc/sp for cpu profiler
   384		MOVL	(SP), SI
   385		MOVL	SI, m_libcallpc(BP)
   386		MOVL	g(CX), SI
   387		MOVL	SI, m_libcallg(BP)
   388		// sp must be the last, because once async cpu profiler finds
   389		// all three values to be non-zero, it will use them
   390		LEAL	fn+0(FP), SI
   391		MOVL	SI, m_libcallsp(BP)
   392	
   393		MOVL	m_g0(BP), SI
   394		CMPL	g(CX), SI
   395		JNE	switch
   396		// executing on m->g0 already
   397		CALL	AX
   398		JMP	ret
   399	
   400	switch:
   401		// Switch to m->g0 stack and back.
   402		MOVL	(g_sched+gobuf_sp)(SI), SI
   403		MOVL	SP, -4(SI)
   404		LEAL	-4(SI), SP
   405		CALL	AX
   406		MOVL	0(SP), SP
   407	
   408	ret:
   409		get_tls(CX)
   410		MOVL	g(CX), BP
   411		MOVL	g_m(BP), BP
   412		MOVL	$0, m_libcallsp(BP)
   413		RET
   414	
   415	// Runs on OS stack. duration (in 100ns units) is in BX.
   416	TEXT runtime·usleep2(SB),NOSPLIT,$20
   417		// Want negative 100ns units.
   418		NEGL	BX
   419		MOVL	$-1, hi-4(SP)
   420		MOVL	BX, lo-8(SP)
   421		LEAL	lo-8(SP), BX
   422		MOVL	BX, ptime-12(SP)
   423		MOVL	$0, alertable-16(SP)
   424		MOVL	$-1, handle-20(SP)
   425		MOVL	SP, BP
   426		MOVL	runtime·_NtWaitForSingleObject(SB), AX
   427		CALL	AX
   428		MOVL	BP, SP
   429		RET
   430	
   431	// Runs on OS stack.
   432	TEXT runtime·switchtothread(SB),NOSPLIT,$0
   433		MOVL	SP, BP
   434		MOVL	runtime·_SwitchToThread(SB), AX
   435		CALL	AX
   436		MOVL	BP, SP
   437		RET
   438	
   439	// See https://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
   440	// Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2.
   441	#define _INTERRUPT_TIME 0x7ffe0008
   442	#define _SYSTEM_TIME 0x7ffe0014
   443	#define time_lo 0
   444	#define time_hi1 4
   445	#define time_hi2 8
   446	
   447	TEXT runtime·nanotime(SB),NOSPLIT,$0-8
   448		CMPB	runtime·useQPCTime(SB), $0
   449		JNE	useQPC
   450	loop:
   451		MOVL	(_INTERRUPT_TIME+time_hi1), AX
   452		MOVL	(_INTERRUPT_TIME+time_lo), CX
   453		MOVL	(_INTERRUPT_TIME+time_hi2), DI
   454		CMPL	AX, DI
   455		JNE	loop
   456	
   457		// wintime = DI:CX, multiply by 100
   458		MOVL	$100, AX
   459		MULL	CX
   460		IMULL	$100, DI
   461		ADDL	DI, DX
   462		// wintime*100 = DX:AX
   463		MOVL	AX, ret_lo+0(FP)
   464		MOVL	DX, ret_hi+4(FP)
   465		RET
   466	useQPC:
   467		JMP	runtime·nanotimeQPC(SB)
   468		RET
   469	
   470	TEXT time·now(SB),NOSPLIT,$0-20
   471		CMPB	runtime·useQPCTime(SB), $0
   472		JNE	useQPC
   473	loop:
   474		MOVL	(_INTERRUPT_TIME+time_hi1), AX
   475		MOVL	(_INTERRUPT_TIME+time_lo), CX
   476		MOVL	(_INTERRUPT_TIME+time_hi2), DI
   477		CMPL	AX, DI
   478		JNE	loop
   479	
   480		// w = DI:CX
   481		// multiply by 100
   482		MOVL	$100, AX
   483		MULL	CX
   484		IMULL	$100, DI
   485		ADDL	DI, DX
   486		// w*100 = DX:AX
   487		MOVL	AX, mono+12(FP)
   488		MOVL	DX, mono+16(FP)
   489	
   490	wall:
   491		MOVL	(_SYSTEM_TIME+time_hi1), CX
   492		MOVL	(_SYSTEM_TIME+time_lo), AX
   493		MOVL	(_SYSTEM_TIME+time_hi2), DX
   494		CMPL	CX, DX
   495		JNE	wall
   496	
   497		// w = DX:AX
   498		// convert to Unix epoch (but still 100ns units)
   499		#define delta 116444736000000000
   500		SUBL	$(delta & 0xFFFFFFFF), AX
   501		SBBL $(delta >> 32), DX
   502	
   503		// nano/100 = DX:AX
   504		// split into two decimal halves by div 1e9.
   505		// (decimal point is two spots over from correct place,
   506		// but we avoid overflow in the high word.)
   507		MOVL	$1000000000, CX
   508		DIVL	CX
   509		MOVL	AX, DI
   510		MOVL	DX, SI
   511	
   512		// DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9
   513		// split DX into seconds and nanoseconds by div 1e7 magic multiply.
   514		MOVL	DX, AX
   515		MOVL	$1801439851, CX
   516		MULL	CX
   517		SHRL	$22, DX
   518		MOVL	DX, BX
   519		IMULL	$10000000, DX
   520		MOVL	SI, CX
   521		SUBL	DX, CX
   522	
   523		// DI = sec/100 (still)
   524		// BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100
   525		// CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100
   526		// store nsec for return
   527		IMULL	$100, CX
   528		MOVL	CX, nsec+8(FP)
   529	
   530		// DI = sec/100 (still)
   531		// BX = sec%100
   532		// construct DX:AX = 64-bit sec and store for return
   533		MOVL	$0, DX
   534		MOVL	$100, AX
   535		MULL	DI
   536		ADDL	BX, AX
   537		ADCL	$0, DX
   538		MOVL	AX, sec+0(FP)
   539		MOVL	DX, sec+4(FP)
   540		RET
   541	useQPC:
   542		JMP	runtime·nowQPC(SB)
   543		RET

View as plain text