...
Run Format

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	
     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 runtime·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	runtime·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	runtime·sigtramp(SB)
   167	
   168	TEXT runtime·ctrlhandler(SB),NOSPLIT,$0
   169		PUSHL	$runtime·ctrlhandler1(SB)
   170		CALL	runtime·externalthreadhandler(SB)
   171		MOVL	4(SP), CX
   172		ADDL	$12, SP
   173		JMP	CX
   174	
   175	TEXT runtime·profileloop(SB),NOSPLIT,$0
   176		PUSHL	$runtime·profileloop1(SB)
   177		CALL	runtime·externalthreadhandler(SB)
   178		MOVL	4(SP), CX
   179		ADDL	$12, SP
   180		JMP	CX
   181	
   182	TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
   183		PUSHL	BP
   184		MOVL	SP, BP
   185		PUSHL	BX
   186		PUSHL	SI
   187		PUSHL	DI
   188		PUSHL	0x14(FS)
   189		MOVL	SP, DX
   190	
   191		// setup dummy m, g
   192		SUBL	$m__size, SP		// space for M
   193		MOVL	SP, 0(SP)
   194		MOVL	$m__size, 4(SP)
   195		CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX
   196	
   197		LEAL	m_tls(SP), CX
   198		MOVL	CX, 0x14(FS)
   199		MOVL	SP, BX
   200		SUBL	$g__size, SP		// space for G
   201		MOVL	SP, g(CX)
   202		MOVL	SP, m_g0(BX)
   203	
   204		MOVL	SP, 0(SP)
   205		MOVL	$g__size, 4(SP)
   206		CALL	runtime·memclrNoHeapPointers(SB)	// smashes AX,BX,CX
   207		LEAL	g__size(SP), BX
   208		MOVL	BX, g_m(SP)
   209	
   210		LEAL	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
   211		MOVL	CX, (g_stack+stack_lo)(SP)
   212		ADDL	$const__StackGuard, CX
   213		MOVL	CX, g_stackguard0(SP)
   214		MOVL	CX, g_stackguard1(SP)
   215		MOVL	DX, (g_stack+stack_hi)(SP)
   216	
   217		PUSHL	AX			// room for return value
   218		PUSHL	16(BP)			// arg for handler
   219		CALL	8(BP)
   220		POPL	CX
   221		POPL	AX			// pass return value to Windows in AX
   222	
   223		get_tls(CX)
   224		MOVL	g(CX), CX
   225		MOVL	(g_stack+stack_hi)(CX), SP
   226		POPL	0x14(FS)
   227		POPL	DI
   228		POPL	SI
   229		POPL	BX
   230		POPL	BP
   231		RET
   232	
   233	GLOBL runtime·cbctxts(SB), NOPTR, $4
   234	
   235	TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
   236	  	MOVL	0(SP), AX	// will use to find our callback context
   237	
   238		// remove return address from stack, we are not returning there
   239		ADDL	$4, SP
   240	
   241		// address to callback parameters into CX
   242		LEAL	4(SP), CX
   243	
   244		// save registers as required for windows callback
   245		PUSHL	DI
   246		PUSHL	SI
   247		PUSHL	BP
   248		PUSHL	BX
   249	
   250		// determine index into runtime·cbctxts table
   251		SUBL	$runtime·callbackasm(SB), AX
   252		MOVL	$0, DX
   253		MOVL	$5, BX	// divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
   254		DIVL	BX
   255	
   256		// find correspondent runtime·cbctxts table entry
   257		MOVL	runtime·cbctxts(SB), BX
   258		MOVL	-4(BX)(AX*4), BX
   259	
   260		// extract callback context
   261		MOVL	wincallbackcontext_gobody(BX), AX
   262		MOVL	wincallbackcontext_argsize(BX), DX
   263	
   264		// preserve whatever's at the memory location that
   265		// the callback will use to store the return value
   266		PUSHL	0(CX)(DX*1)
   267	
   268		// extend argsize by size of return value
   269		ADDL	$4, DX
   270	
   271		// remember how to restore stack on return
   272		MOVL	wincallbackcontext_restorestack(BX), BX
   273		PUSHL	BX
   274	
   275		// call target Go function
   276		PUSHL	DX			// argsize (including return value)
   277		PUSHL	CX			// callback parameters
   278		PUSHL	AX			// address of target Go function
   279		CLD
   280		CALL	runtime·cgocallback_gofunc(SB)
   281		POPL	AX
   282		POPL	CX
   283		POPL	DX
   284	
   285		// how to restore stack on return
   286		POPL	BX
   287	
   288		// return value into AX (as per Windows spec)
   289		// and restore previously preserved value
   290		MOVL	-4(CX)(DX*1), AX
   291		POPL	-4(CX)(DX*1)
   292	
   293		MOVL	BX, CX			// cannot use BX anymore
   294	
   295		// restore registers as required for windows callback
   296		POPL	BX
   297		POPL	BP
   298		POPL	SI
   299		POPL	DI
   300	
   301		// remove callback parameters before return (as per Windows spec)
   302		POPL	DX
   303		ADDL	CX, SP
   304		PUSHL	DX
   305	
   306		CLD
   307	
   308		RET
   309	
   310	// void tstart(M *newm);
   311	TEXT runtime·tstart(SB),NOSPLIT,$0
   312		MOVL	newm+0(FP), CX		// m
   313		MOVL	m_g0(CX), DX		// g
   314	
   315		// Layout new m scheduler stack on os stack.
   316		MOVL	SP, AX
   317		MOVL	AX, (g_stack+stack_hi)(DX)
   318		SUBL	$(64*1024), AX		// stack size
   319		MOVL	AX, (g_stack+stack_lo)(DX)
   320		ADDL	$const__StackGuard, AX
   321		MOVL	AX, g_stackguard0(DX)
   322		MOVL	AX, g_stackguard1(DX)
   323	
   324		// Set up tls.
   325		LEAL	m_tls(CX), SI
   326		MOVL	SI, 0x14(FS)
   327		MOVL	CX, g_m(DX)
   328		MOVL	DX, g(SI)
   329	
   330		// Someday the convention will be D is always cleared.
   331		CLD
   332	
   333		CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   334		CALL	runtime·mstart(SB)
   335	
   336		RET
   337	
   338	// uint32 tstart_stdcall(M *newm);
   339	TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
   340		MOVL	newm+0(FP), BX
   341	
   342		PUSHL	BX
   343		CALL	runtime·tstart(SB)
   344		POPL	BX
   345	
   346		// Adjust stack for stdcall to return properly.
   347		MOVL	(SP), AX		// save return address
   348		ADDL	$4, SP			// remove single parameter
   349		MOVL	AX, (SP)		// restore return address
   350	
   351		XORL	AX, AX			// return 0 == success
   352	
   353		RET
   354	
   355	// setldt(int entry, int address, int limit)
   356	TEXT runtime·setldt(SB),NOSPLIT,$0
   357		MOVL	address+4(FP), CX
   358		MOVL	CX, 0x14(FS)
   359		RET
   360	
   361	// onosstack calls fn on OS stack.
   362	// func onosstack(fn unsafe.Pointer, arg uint32)
   363	TEXT runtime·onosstack(SB),NOSPLIT,$0
   364		MOVL	fn+0(FP), AX		// to hide from 8l
   365		MOVL	arg+4(FP), BX
   366	
   367		// Execute call on m->g0 stack, in case we are not actually
   368		// calling a system call wrapper, like when running under WINE.
   369		get_tls(CX)
   370		CMPL	CX, $0
   371		JNE	3(PC)
   372		// Not a Go-managed thread. Do not switch stack.
   373		CALL	AX
   374		RET
   375	
   376		MOVL	g(CX), BP
   377		MOVL	g_m(BP), BP
   378	
   379		// leave pc/sp for cpu profiler
   380		MOVL	(SP), SI
   381		MOVL	SI, m_libcallpc(BP)
   382		MOVL	g(CX), SI
   383		MOVL	SI, m_libcallg(BP)
   384		// sp must be the last, because once async cpu profiler finds
   385		// all three values to be non-zero, it will use them
   386		LEAL	usec+0(FP), SI
   387		MOVL	SI, m_libcallsp(BP)
   388	
   389		MOVL	m_g0(BP), SI
   390		CMPL	g(CX), SI
   391		JNE	switch
   392		// executing on m->g0 already
   393		CALL	AX
   394		JMP	ret
   395	
   396	switch:
   397		// Switch to m->g0 stack and back.
   398		MOVL	(g_sched+gobuf_sp)(SI), SI
   399		MOVL	SP, -4(SI)
   400		LEAL	-4(SI), SP
   401		CALL	AX
   402		MOVL	0(SP), SP
   403	
   404	ret:
   405		get_tls(CX)
   406		MOVL	g(CX), BP
   407		MOVL	g_m(BP), BP
   408		MOVL	$0, m_libcallsp(BP)
   409		RET
   410	
   411	// Runs on OS stack. duration (in 100ns units) is in BX.
   412	TEXT runtime·usleep2(SB),NOSPLIT,$20
   413		// Want negative 100ns units.
   414		NEGL	BX
   415		MOVL	$-1, hi-4(SP)
   416		MOVL	BX, lo-8(SP)
   417		LEAL	lo-8(SP), BX
   418		MOVL	BX, ptime-12(SP)
   419		MOVL	$0, alertable-16(SP)
   420		MOVL	$-1, handle-20(SP)
   421		MOVL	SP, BP
   422		MOVL	runtime·_NtWaitForSingleObject(SB), AX
   423		CALL	AX
   424		MOVL	BP, SP
   425		RET
   426	
   427	// Runs on OS stack.
   428	TEXT runtime·switchtothread(SB),NOSPLIT,$0
   429		MOVL	SP, BP
   430		MOVL	runtime·_SwitchToThread(SB), AX
   431		CALL	AX
   432		MOVL	BP, SP
   433		RET
   434	
   435	// See http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
   436	// Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2.
   437	#define _INTERRUPT_TIME 0x7ffe0008
   438	#define _SYSTEM_TIME 0x7ffe0014
   439	#define time_lo 0
   440	#define time_hi1 4
   441	#define time_hi2 8
   442	
   443	TEXT runtime·nanotime(SB),NOSPLIT,$0-8
   444		CMPB	runtime·useQPCTime(SB), $0
   445		JNE	useQPC
   446	loop:
   447		MOVL	(_INTERRUPT_TIME+time_hi1), AX
   448		MOVL	(_INTERRUPT_TIME+time_lo), CX
   449		MOVL	(_INTERRUPT_TIME+time_hi2), DI
   450		CMPL	AX, DI
   451		JNE	loop
   452	
   453		// wintime = DI:CX, multiply by 100
   454		MOVL	$100, AX
   455		MULL	CX
   456		IMULL	$100, DI
   457		ADDL	DI, DX
   458		// wintime*100 = DX:AX, subtract startNano and return
   459		SUBL	runtime·startNano+0(SB), AX
   460		SBBL	runtime·startNano+4(SB), DX
   461		MOVL	AX, ret_lo+0(FP)
   462		MOVL	DX, ret_hi+4(FP)
   463		RET
   464	useQPC:
   465		JMP	runtime·nanotimeQPC(SB)
   466		RET
   467	
   468	TEXT time·now(SB),NOSPLIT,$0-20
   469		CMPB	runtime·useQPCTime(SB), $0
   470		JNE	useQPC
   471	loop:
   472		MOVL	(_INTERRUPT_TIME+time_hi1), AX
   473		MOVL	(_INTERRUPT_TIME+time_lo), CX
   474		MOVL	(_INTERRUPT_TIME+time_hi2), DI
   475		CMPL	AX, DI
   476		JNE	loop
   477	
   478		// w = DI:CX
   479		// multiply by 100
   480		MOVL	$100, AX
   481		MULL	CX
   482		IMULL	$100, DI
   483		ADDL	DI, DX
   484		// w*100 = DX:AX
   485		// subtract startNano and save for return
   486		SUBL	runtime·startNano+0(SB), AX
   487		SBBL	runtime·startNano+4(SB), DX
   488		MOVL	AX, mono+12(FP)
   489		MOVL	DX, mono+16(FP)
   490	
   491	wall:
   492		MOVL	(_SYSTEM_TIME+time_hi1), CX
   493		MOVL	(_SYSTEM_TIME+time_lo), AX
   494		MOVL	(_SYSTEM_TIME+time_hi2), DX
   495		CMPL	CX, DX
   496		JNE	wall
   497		
   498		// w = DX:AX
   499		// convert to Unix epoch (but still 100ns units)
   500		#define delta 116444736000000000
   501		SUBL	$(delta & 0xFFFFFFFF), AX
   502		SBBL $(delta >> 32), DX
   503		
   504		// nano/100 = DX:AX
   505		// split into two decimal halves by div 1e9.
   506		// (decimal point is two spots over from correct place,
   507		// but we avoid overflow in the high word.)
   508		MOVL	$1000000000, CX
   509		DIVL	CX
   510		MOVL	AX, DI
   511		MOVL	DX, SI
   512		
   513		// DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9
   514		// split DX into seconds and nanoseconds by div 1e7 magic multiply.
   515		MOVL	DX, AX
   516		MOVL	$1801439851, CX
   517		MULL	CX
   518		SHRL	$22, DX
   519		MOVL	DX, BX
   520		IMULL	$10000000, DX
   521		MOVL	SI, CX
   522		SUBL	DX, CX
   523		
   524		// DI = sec/100 (still)
   525		// BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100
   526		// CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100
   527		// store nsec for return
   528		IMULL	$100, CX
   529		MOVL	CX, nsec+8(FP)
   530	
   531		// DI = sec/100 (still)
   532		// BX = sec%100
   533		// construct DX:AX = 64-bit sec and store for return
   534		MOVL	$0, DX
   535		MOVL	$100, AX
   536		MULL	DI
   537		ADDL	BX, AX
   538		ADCL	$0, DX
   539		MOVL	AX, sec+0(FP)
   540		MOVL	DX, sec+4(FP)
   541		RET
   542	useQPC:
   543		JMP	runtime·nowQPC(SB)
   544		RET

View as plain text