/* ---------------------------------------------- */
/* chkstk86.s */

#ifdef __leading_underscore
# define _(s) _##s
#else
# define _(s) s
#endif

/* ---------------------------------------------- */
#if defined(__aarch64__)

.globl __chkstk
__chkstk:
    /* Windows ARM64 stack probing helper.
       arm64-gen.c passes the requested frame size in x15, scaled in 16-byte
       units. Probe one 4 KiB page at a time and leave SP unchanged; the caller
       subtracts SP after the probe returns. */
    mov     x16, sp
    lsl     x17, x15, 4
    cbz     x17, L_chkstk_done
L_chkstk_loop:
    subs    x0, x17, 4096
    bls     L_chkstk_tail
    sub     x16, x16, 4096
    ldr     xzr, [x16]
    sub     x17, x17, 4096
    b       L_chkstk_loop
L_chkstk_tail:
    sub     x16, x16, x17
    ldr     xzr, [x16]
L_chkstk_done:
    ret

/* ---------------------------------------------- */
#elif defined(__i386__)

.globl _(__chkstk)
_(__chkstk):
    xchg    (%esp),%ebp     /* store ebp, get ret.addr */
    push    %ebp            /* push ret.addr */
    lea     4(%esp),%ebp    /* setup frame ptr */
    push    %ecx            /* save ecx */
    mov     %ebp,%ecx
P0:
    sub     $4096,%ecx
    test    %eax,(%ecx)
    sub     $4096,%eax
    cmp     $4096,%eax
    jge     P0
    sub     %eax,%ecx
    test    %eax,(%ecx)

    mov     %esp,%eax
    mov     %ecx,%esp
    mov     (%eax),%ecx     /* restore ecx */
    jmp     *4(%eax)

/* ---------------------------------------------- */
#else /* __x86_64__ */

.globl _(__chkstk)
_(__chkstk):
    xchg    (%rsp),%rbp     /* store ebp, get ret.addr */
    push    %rbp            /* push ret.addr */
    lea     8(%rsp),%rbp    /* setup frame ptr */
    push    %rcx            /* save ecx */
    mov     %rbp,%rcx
    movslq  %eax,%rax
P0:
    sub     $4096,%rcx
    test    %rax,(%rcx)
    sub     $4096,%rax
    cmp     $4096,%rax
    jge     P0
    sub     %rax,%rcx
    test    %rax,(%rcx)

    mov     %rsp,%rax
    mov     %rcx,%rsp
    mov     (%rax),%rcx     /* restore ecx */
    jmp     *8(%rax)

/* ---------------------------------------------- */
#endif
/* ---------------------------------------------- */
