xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/i386/chkstk.S (revision b3edf4467982447620505a28fc82e38a414c07dc)
10b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
20b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
30b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
40b57cec5SDimitry Andric
50b57cec5SDimitry Andric#include "../assembly.h"
60b57cec5SDimitry Andric
7*5f757f3fSDimitry Andric#ifdef __i386__
8*5f757f3fSDimitry Andric
9*5f757f3fSDimitry Andric// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments,
10*5f757f3fSDimitry Andric// then decrement %esp by %eax.  Preserves all registers except %esp and flags.
110b57cec5SDimitry Andric// This routine is windows specific
120b57cec5SDimitry Andric// http://msdn.microsoft.com/en-us/library/ms648426.aspx
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric.text
150b57cec5SDimitry Andric.balign 4
16*5f757f3fSDimitry AndricDEFINE_COMPILERRT_FUNCTION(_alloca) // _chkstk and _alloca are the same function
170b57cec5SDimitry Andric        push   %ecx
180b57cec5SDimitry Andric        cmp    $0x1000,%eax
19*5f757f3fSDimitry Andric        lea    8(%esp),%ecx     // esp before calling this routine -> ecx
200b57cec5SDimitry Andric        jb     1f
210b57cec5SDimitry Andric2:
220b57cec5SDimitry Andric        sub    $0x1000,%ecx
230b57cec5SDimitry Andric        test   %ecx,(%ecx)
240b57cec5SDimitry Andric        sub    $0x1000,%eax
250b57cec5SDimitry Andric        cmp    $0x1000,%eax
260b57cec5SDimitry Andric        ja     2b
270b57cec5SDimitry Andric1:
280b57cec5SDimitry Andric        sub    %eax,%ecx
290b57cec5SDimitry Andric        test   %ecx,(%ecx)
30*5f757f3fSDimitry Andric
31*5f757f3fSDimitry Andric        lea    4(%esp),%eax     // load pointer to the return address into eax
32*5f757f3fSDimitry Andric        mov    %ecx,%esp        // install the new top of stack pointer into esp
33*5f757f3fSDimitry Andric        mov    -4(%eax),%ecx    // restore ecx
34*5f757f3fSDimitry Andric        push   (%eax)           // push return address onto the stack
35*5f757f3fSDimitry Andric        sub    %esp,%eax        // restore the original value in eax
360b57cec5SDimitry Andric        ret
37*5f757f3fSDimitry AndricEND_COMPILERRT_FUNCTION(_alloca)
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric#endif // __i386__
40