// File: /workspace/github_c_makefile_star2_O1/BernardTatin[P]s7sh/s7.c
// Function: g_apply
static s7_pointer g_apply(s7_scheme *sc, s7_pointer args)
                {
#define H_apply "(apply func ...) applies func to the rest of the arguments"
#define Q_apply s7_make_circular_signature(sc, 2, 3, sc->values_symbol, s7_make_signature(sc, 2, sc->is_procedure_symbol, sc->is_sequence_symbol), sc->T)

                    /* can apply always be replaced with apply values?
                     *   (apply + '(1 2 3)) is the same as (+ (apply values '(1 2 3)))
                     * not if apply* in disguise, I think:
                     *   (apply + 1 2 ()) -> 3
                     *   (apply + 1 2 (apply values ())) -> error
                     */
                    sc->code = car(args);
                    if (is_null(cdr(args)))
                    {
                        sc->args = sc->nil;
                        push_stack(sc, OP_APPLY, sc->args, sc->code);
                        return(sc->nil);
                    }

                    if (is_safe_procedure(sc->code))
                    {
                        s7_pointer p, q;

                        for (q = args, p = cdr(args); is_not_null(cdr(p)); q = p, p = cdr(p));
                        /* the last arg is supposed to be a list, it will be spliced onto the end of the previous arg list (if any) below */

                        if (!s7_is_proper_list(sc, car(p)))        /* (apply + #f) etc */
                            return(apply_list_error(sc, args));
                        set_cdr(q, car(p));
                        /* this would work: if (is_c_function(sc->code)) return(c_function_call(sc->code)(sc, cdr(args)));
                         *   but it omits the arg number check, but if we copy the APPLY table here (returning sc->value)
                         *   the overhead from the now non-inline function calls is greater than the fewer-eval-jumps savings.
                         */
                        push_stack(sc, OP_APPLY, cdr(args), sc->code);
                        return(sc->nil);
                    }

                    /* here we may have to copy the arg list */
                    if (is_null(cddr(args)))
                        sc->args = cadr(args);
                    else sc->args = apply_list_star(sc, cdr(args));
                    if (!s7_is_proper_list(sc, sc->args))
                        return(apply_list_error(sc, args));

                    push_stack(sc, OP_APPLY, (needs_copied_args(sc->code)) ? copy_list(sc, sc->args) : sc->args, sc->code);
                    return(sc->nil);
                }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movq 0x8(%rsi), %rcx
movq %rcx, (%rdi)
movq 0x10(%rsi), %r12
movq 0x110(%rdi), %rax
cmpq %rax, %r12
je 0x8344e
movq %rsi, %r14
testb $0x20, 0x2(%rcx)
jne 0x8346b
movq 0x8(%r12), %r15
movq 0x10(%r12), %rbp
cmpq %rax, %rbp
je 0x83408
movq 0x90(%rbx), %rax
cmpq 0x98(%rbx), %rax
ja 0x8334b
movq %rbx, %rdi
callq 0xb389
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %r13
movq $0x200001, (%r13)       # imm = 0x200001
movq %r15, 0x8(%r13)
leaq 0x10(%r13), %r15
movq %rbp, 0x10(%r13)
movq %r13, 0x4d8(%rbx)
movq 0x10(%r13), %rax
movq 0x10(%rax), %rcx
cmpq 0x110(%rbx), %rcx
je 0x833fa
movq 0x10(%r12), %r12
movups 0x8(%r12), %xmm0
movq 0x90(%rbx), %rax
cmpq 0x98(%rbx), %rax
ja 0x833b8
movq %rbx, %rdi
movaps %xmm0, (%rsp)
callq 0xb389
movaps (%rsp), %xmm0
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %rax
movq $0x200001, (%rax)       # imm = 0x200001
movups %xmm0, 0x8(%rax)
movq %rax, (%r15)
movq 0x110(%rbx), %rcx
cmpq %rcx, 0x10(%r12)
cmovneq %rax, %r13
leaq 0x10(%r13), %r15
movq 0x10(%r13), %rax
cmpq %rcx, 0x10(%rax)
jne 0x8338d
movq 0x8(%rax), %rax
movq %rax, (%r15)
movq 0x4d8(%rbx), %r15
movq %r15, 0x10(%rbx)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3c2fb
testb %al, %al
je 0x834bc
movq (%rbx), %rax
movq 0x50(%rbx), %rcx
movq %rax, (%rcx)
movq 0x8(%rbx), %rax
movq 0x50(%rbx), %rcx
movq %rax, 0x8(%rcx)
movq (%rbx), %rax
movq 0x10(%rbx), %r15
testb $0x10, 0x3(%rax)
jne 0x834d5
movq %r15, %r14
jmp 0x835ba
movq %rax, 0x10(%rbx)
movq 0x50(%rbx), %rax
movq %rcx, (%rax)
movq 0x8(%rbx), %rax
movq 0x50(%rbx), %rcx
movq %rax, 0x8(%rcx)
movq 0x10(%rbx), %rax
jmp 0x834af
movq %r14, %rcx
movq %rcx, %r13
movq %r12, %rcx
movq 0x10(%r12), %r12
cmpq %rax, %r12
jne 0x8346e
movq 0x8(%rcx), %r15
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3c2fb
testb %al, %al
je 0x834bc
movq %r15, 0x10(%r13)
movq (%rbx), %rax
movq 0x50(%rbx), %rcx
movq %rax, (%rcx)
movq 0x8(%rbx), %rax
movq 0x50(%rbx), %rcx
movq %rax, 0x8(%rcx)
movq 0x10(%r14), %rax
movq 0x50(%rbx), %rcx
movq %rax, 0x10(%rcx)
jmp 0x835c2
movq %rbx, %rdi
movq %r14, %rsi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xd568c
cmpb $0x1, (%r15)
jne 0x835b3
movq %r15, 0x4c8(%rbx)
movq 0x8(%r15), %r12
movq 0x90(%rbx), %rax
movq 0x110(%rbx), %r13
cmpq 0x98(%rbx), %rax
ja 0x83509
movq %rbx, %rdi
callq 0xb389
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %r14
movq $0x200001, (%r14)       # imm = 0x200001
movq %r12, 0x8(%r14)
movq %r13, 0x10(%r14)
movq %r14, 0x4e8(%rbx)
movq 0x10(%r15), %r15
cmpb $0x1, (%r15)
jne 0x8359c
movq %r14, %r12
movq 0x8(%r15), %r13
movq 0x90(%rbx), %rax
movq 0x110(%rbx), %rbp
cmpq 0x98(%rbx), %rax
ja 0x83565
movq %rbx, %rdi
callq 0xb389
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %rax
movq $0x200001, (%rax)       # imm = 0x200001
movq %r13, 0x8(%rax)
movq %rbp, 0x10(%rax)
movq %rax, 0x10(%r12)
movq 0x10(%r15), %r15
cmpb $0x1, (%r15)
movq %rax, %r12
je 0x83542
movq 0x110(%rbx), %rax
movq %rax, 0x4e8(%rbx)
movq %rax, 0x4c8(%rbx)
jmp 0x835ba
movq 0x110(%rbx), %r14
movq 0x50(%rbx), %rax
movq %r14, 0x10(%rax)
movq 0x50(%rbx), %rax
movq $0x198, 0x18(%rax)      # imm = 0x198
addq $0x20, 0x50(%rbx)
movq 0x110(%rbx), %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq