// File: /workspace/github_c_makefile_star2_O3/hoobaa[P]ficl/primitives.c
// Function: ficlPrimitiveCatch
static void ficlPrimitiveCatch(ficlVm *vm)
{
    int         except;
    jmp_buf     vmState;
    ficlVm     vmCopy;
    ficlStack  dataStackCopy;
    ficlStack  returnStackCopy;
    ficlWord   *word;

    FICL_VM_ASSERT(vm, vm);
    FICL_VM_ASSERT(vm, vm->callback.system->exitInnerWord);
    

    /*
    ** Get xt.
    ** We need this *before* we save the stack pointer, or
    ** we'll have to pop one element out of the stack after
    ** an exception. I prefer to get done with it up front. :-)
    */

    FICL_STACK_CHECK(vm->dataStack, 1, 0);

    word = ficlStackPopPointer(vm->dataStack);

    /* 
    ** Save vm's state -- a catch will not back out environmental
    ** changes.
    **
    ** We are *not* saving dictionary state, since it is
    ** global instead of per vm, and we are not saving
    ** stack contents, since we are not required to (and,
    ** thus, it would be useless). We save vm, and vm
    ** "stacks" (a structure containing general information
    ** about it, including the current stack pointer).
    */
    memcpy((void*)&vmCopy, (void*)vm, sizeof(ficlVm));
    memcpy((void*)&dataStackCopy, (void*)vm->dataStack, sizeof(ficlStack));
    memcpy((void*)&returnStackCopy, (void*)vm->returnStack, sizeof(ficlStack));

    /*
    ** Give vm a jmp_buf
    */
    vm->exceptionHandler = &vmState;

    /*
    ** Safety net
    */
    except = setjmp(vmState);

    switch (except)
    {
        /*
        ** Setup condition - push poison pill so that the VM throws
        ** VM_INNEREXIT if the XT terminates normally, then execute
        ** the XT
        */
    case 0:
        ficlVmPushIP(vm, &(vm->callback.system->exitInnerWord));          /* Open mouth, insert emetic */
        ficlVmExecuteWord(vm, word);
        ficlVmInnerLoop(vm, 0);
        break;

        /*
        ** Normal exit from XT - lose the poison pill, 
        ** restore old setjmp vector and push a zero. 
        */
    case FICL_VM_STATUS_INNER_EXIT:
        ficlVmPopIP(vm);                   /* Gack - hurl poison pill */
        vm->exceptionHandler = vmCopy.exceptionHandler;        /* Restore just the setjmp vector */
        ficlStackPushInteger(vm->dataStack, 0);   /* Push 0 -- everything is ok */
        break;

        /*
        ** Some other exception got thrown - restore pre-existing VM state
        ** and push the exception code
        */
    default:
        /* Restore vm's state */
        memcpy((void*)vm, (void*)&vmCopy, sizeof(ficlVm));
        memcpy((void*)vm->dataStack, (void*)&dataStackCopy, sizeof(ficlStack));
        memcpy((void*)vm->returnStack, (void*)&returnStackCopy, sizeof(ficlStack));

        ficlStackPushInteger(vm->dataStack, except);/* Push error */
        break;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0xa40, %rsp            # imm = 0xA40
movq %rdi, %rbx
movq 0x60(%rdi), %rdi
callq 0x429d
movq %rax, %r15
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movups 0x20(%rbx), %xmm2
movaps %xmm0, 0x60(%rsp)
movaps %xmm1, 0x70(%rsp)
movaps %xmm2, 0x80(%rsp)
movq 0x30(%rbx), %r12
leaq 0x38(%rbx), %r14
leaq 0x160(%rsp), %rdi
movl $0x8e0, %edx            # imm = 0x8E0
movq %r14, %rsi
callq 0x3200
movq 0x60(%rbx), %rax
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movaps %xmm0, 0x30(%rsp)
movaps %xmm1, 0x40(%rsp)
movaps %xmm2, 0x50(%rsp)
movq 0x68(%rbx), %rax
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movaps %xmm2, 0x20(%rsp)
movaps %xmm0, (%rsp)
movaps %xmm1, 0x10(%rsp)
leaq 0x90(%rsp), %rdi
movq %rdi, 0x30(%rbx)
callq 0x3180
cmpl $0xffffff00, %eax       # imm = 0xFFFFFF00
je 0xa6af
movl %eax, %ebp
testl %eax, %eax
jne 0xa6c5
movl $0xa0, %esi
addq 0x18(%rbx), %rsi
movq %rbx, %rdi
callq 0x6ad9
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5351
xorl %eax, %eax
movl %eax, %esi
movq %rbx, %rdi
callq 0x5356
jmp 0xa742
movq %rbx, %rdi
callq 0x6ac6
movq %r12, 0x30(%rbx)
movq 0x60(%rbx), %rdi
xorl %eax, %eax
movl %eax, %esi
jmp 0xa73d
movaps 0x60(%rsp), %xmm0
movaps 0x70(%rsp), %xmm1
movaps 0x80(%rsp), %xmm2
movups %xmm2, 0x20(%rbx)
movups %xmm1, 0x10(%rbx)
movups %xmm0, (%rbx)
movq %r12, 0x30(%rbx)
leaq 0x160(%rsp), %rsi
movl $0x8e0, %edx            # imm = 0x8E0
movq %r14, %rdi
callq 0x3200
movq 0x60(%rbx), %rax
movaps 0x30(%rsp), %xmm0
movaps 0x40(%rsp), %xmm1
movaps 0x50(%rsp), %xmm2
movups %xmm0, (%rax)
movups %xmm1, 0x10(%rax)
movups %xmm2, 0x20(%rax)
movq 0x68(%rbx), %rax
movaps (%rsp), %xmm0
movaps 0x10(%rsp), %xmm1
movaps 0x20(%rsp), %xmm2
movups %xmm1, 0x10(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm0, (%rax)
movq 0x60(%rbx), %rdi
movslq %ebp, %rsi
callq 0x4327
addq $0xa40, %rsp            # imm = 0xA40
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq