summaryrefslogtreecommitdiffstats
path: root/src/kash/shforkA-win.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/kash/shforkA-win.asm')
-rw-r--r--src/kash/shforkA-win.asm338
1 files changed, 338 insertions, 0 deletions
diff --git a/src/kash/shforkA-win.asm b/src/kash/shforkA-win.asm
new file mode 100644
index 0000000..6db4f28
--- /dev/null
+++ b/src/kash/shforkA-win.asm
@@ -0,0 +1,338 @@
+; $Id: shforkA-win.asm 2416 2010-09-14 00:30:30Z bird $
+;; @file
+; shforkA-win.asm - assembly routines used when forking on Windows.
+;
+
+;
+; Copyright (c) 2009-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+;
+; This file is part of kBuild.
+;
+; kBuild is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 3 of the License, or
+; (at your option) any later version.
+;
+; kBuild is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with kBuild. If not, see <http://www.gnu.org/licenses/>
+;
+;
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%ifdef KBUILD_ARCH_AMD64
+ %define NAME(name) name
+%else
+ %define NAME(name) _ %+ name
+%endif
+
+;; The stack size. This is also defined in shfork-win.c.
+%define SHFORK_STACK_SIZE (1*1024*1024)
+
+
+;*******************************************************************************
+;* External Symbols *
+;*******************************************************************************
+extern NAME(real_main)
+extern NAME(shfork_maybe_forked)
+extern NAME(shfork_body)
+
+
+[section .text]
+
+;;
+; C main() wrapper.
+;
+NAME(main):
+global NAME(main)
+%ifdef KBUILD_ARCH_AMD64
+[proc_frame main]
+%endif
+
+ ;
+ ; Prolog, spilling parameters from registers.
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ [pushreg rbp]
+ push rbp
+ [setframe rbp, 0]
+ mov rbp, rsp
+ [allocstack 0x40]
+ sub rsp, 40h
+ and rsp, ~1fh
+ mov [rbp-08h], rcx ; argc
+ mov [rbp-10h], rdx ; argv
+ mov [rbp-18h], r8 ; envp
+ [endprolog]
+%else
+ push ebp
+ mov ebp, esp
+ sub esp, 40h
+ and esp, ~1fh
+%endif
+
+ ;
+ ; Call shfork_maybe_forked. This will not return if we're forking.
+ ;
+%ifndef KBUILD_ARCH_AMD64
+ mov ecx, [ebp + 8h] ; argc
+ mov edx, [ebp + 0ch] ; argv
+ mov eax, [ebp + 10h] ; envp
+ mov [esp ], ecx
+ mov [esp + 4h], edx
+ mov [esp + 8h], eax
+%endif
+ call NAME(shfork_maybe_forked)
+
+ ;
+ ; Ok, it returned which means we're not forking.
+ ;
+ ; The accumulator register is now pointing to the top of the
+ ; stack we're going to call real_main on. Switch and call it.
+ ;
+ ; The TIB adjustments is required or we'll crash in longjmp/unwind.
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ mov [rsp + 18h], rax
+ mov [rax - 8h], rsp
+
+ mov r10, [gs:08h] ; StackBase (the higher value)
+ mov r11, [gs:10h] ; StackLimit (the lower value)
+ mov [rax - 10h], r10
+ mov [rax - 18h], r11
+ cmp rax, r10
+ jb .below
+ mov [gs:08h], rax
+.below:
+ lea r9, [rax - SHFORK_STACK_SIZE]
+ cmp r9, r11
+ ja .above
+ mov [gs:10h], r9
+.above:
+
+ mov rcx, [rbp - 08h] ; argc
+ mov rdx, [rbp - 10h] ; argv
+ mov r8, [rbp - 18h] ; envp
+
+ lea rsp, [rax - 40h] ; Switch!
+%else
+ mov [esp + 18h], eax
+ mov [eax - 4], esp
+ lea esp, [eax - 40h] ; Switch!
+
+ mov edx, [fs:04h] ; StackBase (the higher value)
+ mov ecx, [fs:08h] ; StackLimit (the lower value)
+ mov [eax - 10h], edx
+ mov [eax - 18h], ecx
+ cmp eax, edx
+ jb .below
+ mov [fs:04h], eax
+.below:
+ lea edx, [eax - SHFORK_STACK_SIZE]
+ cmp edx, ecx
+ ja .above
+ mov [fs:08h], edx
+.above:
+
+ mov ecx, [ebp + 8h] ; argc
+ mov edx, [ebp + 0ch] ; argv
+ mov eax, [ebp + 10h] ; envp
+
+ mov [esp ], ecx
+ mov [esp + 4h], edx
+ mov [esp + 8h], eax
+%endif
+ call NAME(real_main)
+
+ ;
+ ; Switch back the stack, restore the TIB fields and we're done.
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ lea r11, [rsp + 40h]
+ mov rsp, [rsp + 38h]
+ mov r8, [r11 - 10h]
+ mov r9, [r11 - 18h]
+ mov [gs:08h], r8
+ mov [gs:10h], r9
+%else
+ lea edx, [esp + 40h]
+ mov esp, [esp + 2ch]
+ mov ecx, [edx - 10h]
+ mov edx, [edx - 18h]
+ mov [fs:04h], ecx
+ mov [fs:08h], edx
+%endif
+ leave
+ ret
+%ifdef KBUILD_ARCH_AMD64
+[endproc_frame main]
+%endif
+
+
+;;
+; sh_fork() worker
+;
+; @returns See fork().
+; @param psh
+;
+NAME(shfork_do_it):
+global NAME(shfork_do_it)
+%ifdef KBUILD_ARCH_AMD64
+ [proc_frame shfork_do_it]
+ [pushreg rbp]
+ push rbp
+ [setframe rbp, 0]
+ mov rbp, rsp
+ [allocstack 0x400]
+ sub rsp, 400h
+ and rsp, ~1ffh
+[endprolog]
+%else
+ push ebp
+ mov ebp, esp
+ sub esp, 400h
+ and esp, ~1ffh
+%endif
+
+ ;
+ ; Save most registers so they can be restored in the child.
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ fxsave [rsp]
+ mov [rsp + 200h], rbp
+ mov [rsp + 208h], rax
+ mov [rsp + 210h], rbx
+ mov [rsp + 218h], rcx
+ mov [rsp + 220h], rdx
+ mov [rsp + 228h], rsi
+ mov [rsp + 230h], rdi
+ mov [rsp + 238h], r8
+ mov [rsp + 240h], r9
+ mov [rsp + 248h], r10
+ mov [rsp + 250h], r11
+ mov [rsp + 258h], r12
+ mov [rsp + 260h], r13
+ mov [rsp + 268h], r14
+ mov [rsp + 270h], r15
+%else
+ fxsave [esp]
+ mov [esp + 200h], ebp
+ mov [esp + 208h], eax
+ mov [esp + 210h], ebx
+ mov [esp + 218h], ecx
+ mov [esp + 220h], edx
+ mov [esp + 228h], esi
+ mov [esp + 230h], edi
+%endif
+
+ ;
+ ; Call the shfork_body that will spawn the child and all that.
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ ;mov rcx, rcx ; psh
+ mov rdx, rsp ; stack_ptr
+ sub rsp, 20h
+ call NAME(shfork_body)
+ lea rsp, [rsp + 20h]
+%else
+ mov edx, esp
+ mov ecx, [ebp + 8h] ; psh
+ sub esp, 20h
+ mov [esp ], ecx
+ mov [esp + 4], edx ; stack_ptr
+ call NAME(shfork_body)
+ lea esp, [esp + 20h]
+%endif
+
+ ;
+ ; Just leave the function, no need to restore things.
+ ;
+ leave
+ ret
+%ifdef KBUILD_ARCH_AMD64
+[endproc_frame shfork_do_it]
+%endif
+
+
+;;
+; Switch the stack, restore the register and leave as if we'd called shfork_do_it.
+;
+; @param cur Current stack pointer.
+; @param base The stack base (higher value).
+; @param limit The stack limit (lower value).
+;
+NAME(shfork_resume):
+global NAME(shfork_resume)
+%ifdef KBUILD_ARCH_AMD64
+ mov rsp, rcx
+%else
+ mov ecx, [esp + 4]
+ mov edx, [esp + 8]
+ mov eax, [esp + 12]
+ mov esp, ecx
+%endif
+
+ ;
+ ; Adjust stack stuff in the TIB (longjmp/unwind).
+ ;
+%ifdef KBUILD_ARCH_AMD64
+ cmp rdx, [gs:08h] ; StackBase (the higher value)
+ jb .below
+ mov [gs:08h], rdx
+.below:
+ cmp r8, [gs:10h] ; StackLimit
+ ja .above
+ mov [gs:10h], r8
+.above:
+%else
+ cmp edx, [fs:04h] ; StackBase (the higher value)
+ jb .below
+ mov [fs:04h], edx
+.below:
+ cmp eax, [fs:08h] ; StackLimit
+ ja .above
+ mov [fs:08h], eax
+.above:
+%endif
+
+ ;
+ ; Restore most of the registers.
+ ;
+ ;; @todo xmm registers may require explicit saving/restoring...
+%ifdef KBUILD_ARCH_AMD64
+ frstor [rsp]
+ mov rbp, [rsp + 200h]
+ mov rax, [rsp + 208h]
+ mov rbx, [rsp + 210h]
+ mov rcx, [rsp + 218h]
+ mov rdx, [rsp + 220h]
+ mov rsi, [rsp + 228h]
+ mov rdi, [rsp + 230h]
+ mov r8, [rsp + 238h]
+ mov r9, [rsp + 240h]
+ mov r10, [rsp + 248h]
+ mov r11, [rsp + 250h]
+ mov r12, [rsp + 258h]
+ mov r13, [rsp + 260h]
+ mov r14, [rsp + 268h]
+ mov r15, [rsp + 270h]
+%else
+ frstor [esp]
+ mov ebp, [esp + 200h]
+ mov eax, [esp + 208h]
+ mov ebx, [esp + 210h]
+ mov ecx, [esp + 218h]
+ mov edx, [esp + 220h]
+ mov esi, [esp + 228h]
+ mov edi, [esp + 230h]
+%endif
+ xor eax, eax ; the child returns 0.
+ leave
+ ret
+