diff options
Diffstat (limited to 'src/kash/shforkA-win.asm')
-rw-r--r-- | src/kash/shforkA-win.asm | 338 |
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 + |