summaryrefslogtreecommitdiffstats
path: root/src/runtime/sys_windows_386.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/sys_windows_386.s')
-rw-r--r--src/runtime/sys_windows_386.s358
1 files changed, 358 insertions, 0 deletions
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
new file mode 100644
index 0000000..cf3a439
--- /dev/null
+++ b/src/runtime/sys_windows_386.s
@@ -0,0 +1,358 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+#include "time_windows.h"
+
+// void runtime·asmstdcall(void *c);
+TEXT runtime·asmstdcall(SB),NOSPLIT,$0
+ MOVL fn+0(FP), BX
+
+ // SetLastError(0).
+ MOVL $0, 0x34(FS)
+
+ // Copy args to the stack.
+ MOVL SP, BP
+ MOVL libcall_n(BX), CX // words
+ MOVL CX, AX
+ SALL $2, AX
+ SUBL AX, SP // room for args
+ MOVL SP, DI
+ MOVL libcall_args(BX), SI
+ CLD
+ REP; MOVSL
+
+ // Call stdcall or cdecl function.
+ // DI SI BP BX are preserved, SP is not
+ CALL libcall_fn(BX)
+ MOVL BP, SP
+
+ // Return result.
+ MOVL fn+0(FP), BX
+ MOVL AX, libcall_r1(BX)
+ MOVL DX, libcall_r2(BX)
+
+ // GetLastError().
+ MOVL 0x34(FS), AX
+ MOVL AX, libcall_err(BX)
+
+ RET
+
+TEXT runtime·badsignal2(SB),NOSPLIT,$24
+ // stderr
+ MOVL $-12, 0(SP)
+ MOVL SP, BP
+ CALL *runtime·_GetStdHandle(SB)
+ MOVL BP, SP
+
+ MOVL AX, 0(SP) // handle
+ MOVL $runtime·badsignalmsg(SB), DX // pointer
+ MOVL DX, 4(SP)
+ MOVL runtime·badsignallen(SB), DX // count
+ MOVL DX, 8(SP)
+ LEAL 20(SP), DX // written count
+ MOVL $0, 0(DX)
+ MOVL DX, 12(SP)
+ MOVL $0, 16(SP) // overlapped
+ CALL *runtime·_WriteFile(SB)
+
+ // Does not return.
+ CALL runtime·abort(SB)
+ RET
+
+// faster get/set last error
+TEXT runtime·getlasterror(SB),NOSPLIT,$0
+ MOVL 0x34(FS), AX
+ MOVL AX, ret+0(FP)
+ RET
+
+// Called by Windows as a Vectored Exception Handler (VEH).
+// First argument is pointer to struct containing
+// exception record and context pointers.
+// Handler function is stored in AX.
+// Return 0 for 'not handled', -1 for handled.
+TEXT sigtramp<>(SB),NOSPLIT,$0-0
+ MOVL ptrs+0(FP), CX
+ SUBL $40, SP
+
+ // save callee-saved registers
+ MOVL BX, 28(SP)
+ MOVL BP, 16(SP)
+ MOVL SI, 20(SP)
+ MOVL DI, 24(SP)
+
+ MOVL AX, SI // save handler address
+
+ // find g
+ get_tls(DX)
+ CMPL DX, $0
+ JNE 3(PC)
+ MOVL $0, AX // continue
+ JMP done
+ MOVL g(DX), DX
+ CMPL DX, $0
+ JNE 2(PC)
+ CALL runtime·badsignal2(SB)
+
+ // save g in case of stack switch
+ MOVL DX, 32(SP) // g
+ MOVL SP, 36(SP)
+
+ // do we need to switch to the g0 stack?
+ MOVL g_m(DX), BX
+ MOVL m_g0(BX), BX
+ CMPL DX, BX
+ JEQ g0
+
+ // switch to the g0 stack
+ get_tls(BP)
+ MOVL BX, g(BP)
+ MOVL (g_sched+gobuf_sp)(BX), DI
+ // make room for sighandler arguments
+ // and re-save old SP for restoring later.
+ // (note that the 36(DI) here must match the 36(SP) above.)
+ SUBL $40, DI
+ MOVL SP, 36(DI)
+ MOVL DI, SP
+
+g0:
+ MOVL 0(CX), BX // ExceptionRecord*
+ MOVL 4(CX), CX // Context*
+ MOVL BX, 0(SP)
+ MOVL CX, 4(SP)
+ MOVL DX, 8(SP)
+ CALL SI // call handler
+ // AX is set to report result back to Windows
+ MOVL 12(SP), AX
+
+ // switch back to original stack and g
+ // no-op if we never left.
+ MOVL 36(SP), SP
+ MOVL 32(SP), DX // note: different SP
+ get_tls(BP)
+ MOVL DX, g(BP)
+
+done:
+ // restore callee-saved registers
+ MOVL 24(SP), DI
+ MOVL 20(SP), SI
+ MOVL 16(SP), BP
+ MOVL 28(SP), BX
+
+ ADDL $40, SP
+ // RET 4 (return and pop 4 bytes parameters)
+ BYTE $0xC2; WORD $4
+ RET // unreached; make assembler happy
+
+TEXT runtime·exceptiontramp(SB),NOSPLIT,$0
+ MOVL $runtime·exceptionhandler(SB), AX
+ JMP sigtramp<>(SB)
+
+TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0
+ // is never called
+ INT $3
+
+TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0
+ MOVL $runtime·lastcontinuehandler(SB), AX
+ JMP sigtramp<>(SB)
+
+GLOBL runtime·cbctxts(SB), NOPTR, $4
+
+TEXT runtime·callbackasm1(SB),NOSPLIT,$0
+ MOVL 0(SP), AX // will use to find our callback context
+
+ // remove return address from stack, we are not returning to callbackasm, but to its caller.
+ ADDL $4, SP
+
+ // address to callback parameters into CX
+ LEAL 4(SP), CX
+
+ // save registers as required for windows callback
+ PUSHL DI
+ PUSHL SI
+ PUSHL BP
+ PUSHL BX
+
+ // Go ABI requires DF flag to be cleared.
+ CLD
+
+ // determine index into runtime·cbs table
+ SUBL $runtime·callbackasm(SB), AX
+ MOVL $0, DX
+ MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long
+ DIVL BX
+ SUBL $1, AX // subtract 1 because return PC is to the next slot
+
+ // Create a struct callbackArgs on our stack.
+ SUBL $(12+callbackArgs__size), SP
+ MOVL AX, (12+callbackArgs_index)(SP) // callback index
+ MOVL CX, (12+callbackArgs_args)(SP) // address of args vector
+ MOVL $0, (12+callbackArgs_result)(SP) // result
+ LEAL 12(SP), AX // AX = &callbackArgs{...}
+
+ // Call cgocallback, which will call callbackWrap(frame).
+ MOVL $0, 8(SP) // context
+ MOVL AX, 4(SP) // frame (address of callbackArgs)
+ LEAL ·callbackWrap(SB), AX
+ MOVL AX, 0(SP) // PC of function to call
+ CALL runtime·cgocallback(SB)
+
+ // Get callback result.
+ MOVL (12+callbackArgs_result)(SP), AX
+ // Get popRet.
+ MOVL (12+callbackArgs_retPop)(SP), CX // Can't use a callee-save register
+ ADDL $(12+callbackArgs__size), SP
+
+ // restore registers as required for windows callback
+ POPL BX
+ POPL BP
+ POPL SI
+ POPL DI
+
+ // remove callback parameters before return (as per Windows spec)
+ POPL DX
+ ADDL CX, SP
+ PUSHL DX
+
+ CLD
+
+ RET
+
+// void tstart(M *newm);
+TEXT tstart<>(SB),NOSPLIT,$0
+ MOVL newm+0(FP), CX // m
+ MOVL m_g0(CX), DX // g
+
+ // Layout new m scheduler stack on os stack.
+ MOVL SP, AX
+ MOVL AX, (g_stack+stack_hi)(DX)
+ SUBL $(64*1024), AX // initial stack size (adjusted later)
+ MOVL AX, (g_stack+stack_lo)(DX)
+ ADDL $const__StackGuard, AX
+ MOVL AX, g_stackguard0(DX)
+ MOVL AX, g_stackguard1(DX)
+
+ // Set up tls.
+ LEAL m_tls(CX), SI
+ MOVL SI, 0x14(FS)
+ MOVL CX, g_m(DX)
+ MOVL DX, g(SI)
+
+ // Someday the convention will be D is always cleared.
+ CLD
+
+ CALL runtime·stackcheck(SB) // clobbers AX,CX
+ CALL runtime·mstart(SB)
+
+ RET
+
+// uint32 tstart_stdcall(M *newm);
+TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
+ MOVL newm+0(FP), BX
+
+ PUSHL BX
+ CALL tstart<>(SB)
+ POPL BX
+
+ // Adjust stack for stdcall to return properly.
+ MOVL (SP), AX // save return address
+ ADDL $4, SP // remove single parameter
+ MOVL AX, (SP) // restore return address
+
+ XORL AX, AX // return 0 == success
+
+ RET
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),NOSPLIT,$0
+ MOVL base+4(FP), CX
+ MOVL CX, 0x14(FS)
+ RET
+
+// Runs on OS stack.
+// duration (in -100ns units) is in dt+0(FP).
+// g may be nil.
+TEXT runtime·usleep2(SB),NOSPLIT,$20-4
+ MOVL dt+0(FP), BX
+ MOVL $-1, hi-4(SP)
+ MOVL BX, lo-8(SP)
+ LEAL lo-8(SP), BX
+ MOVL BX, ptime-12(SP)
+ MOVL $0, alertable-16(SP)
+ MOVL $-1, handle-20(SP)
+ MOVL SP, BP
+ MOVL runtime·_NtWaitForSingleObject(SB), AX
+ CALL AX
+ MOVL BP, SP
+ RET
+
+// Runs on OS stack.
+// duration (in -100ns units) is in dt+0(FP).
+// g is valid.
+TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36-4
+ MOVL dt+0(FP), BX
+ MOVL $-1, hi-4(SP)
+ MOVL BX, lo-8(SP)
+
+ get_tls(CX)
+ MOVL g(CX), CX
+ MOVL g_m(CX), CX
+ MOVL (m_mOS+mOS_highResTimer)(CX), CX
+ MOVL CX, saved_timer-12(SP)
+
+ MOVL $0, fResume-16(SP)
+ MOVL $0, lpArgToCompletionRoutine-20(SP)
+ MOVL $0, pfnCompletionRoutine-24(SP)
+ MOVL $0, lPeriod-28(SP)
+ LEAL lo-8(SP), BX
+ MOVL BX, lpDueTime-32(SP)
+ MOVL CX, hTimer-36(SP)
+ MOVL SP, BP
+ MOVL runtime·_SetWaitableTimer(SB), AX
+ CALL AX
+ MOVL BP, SP
+
+ MOVL $0, ptime-28(SP)
+ MOVL $0, alertable-32(SP)
+ MOVL saved_timer-12(SP), CX
+ MOVL CX, handle-36(SP)
+ MOVL SP, BP
+ MOVL runtime·_NtWaitForSingleObject(SB), AX
+ CALL AX
+ MOVL BP, SP
+
+ RET
+
+// Runs on OS stack.
+TEXT runtime·switchtothread(SB),NOSPLIT,$0
+ MOVL SP, BP
+ MOVL runtime·_SwitchToThread(SB), AX
+ CALL AX
+ MOVL BP, SP
+ RET
+
+TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
+ CMPB runtime·useQPCTime(SB), $0
+ JNE useQPC
+loop:
+ MOVL (_INTERRUPT_TIME+time_hi1), AX
+ MOVL (_INTERRUPT_TIME+time_lo), CX
+ MOVL (_INTERRUPT_TIME+time_hi2), DI
+ CMPL AX, DI
+ JNE loop
+
+ // wintime = DI:CX, multiply by 100
+ MOVL $100, AX
+ MULL CX
+ IMULL $100, DI
+ ADDL DI, DX
+ // wintime*100 = DX:AX
+ MOVL AX, ret_lo+0(FP)
+ MOVL DX, ret_hi+4(FP)
+ RET
+useQPC:
+ JMP runtime·nanotimeQPC(SB)
+ RET