// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xa70, %rsp            # imm = 0xA70
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x4b30
movq %rax, -0xa68(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x9f8(%rbp), %rdi
movl $0x918, %edx            # imm = 0x918
callq 0x31e0
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movaps %xmm2, -0xa10(%rbp)
movaps %xmm1, -0xa20(%rbp)
movaps %xmm0, -0xa30(%rbp)
movq -0x8(%rbp), %rax
movq 0x68(%rax), %rax
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movaps %xmm2, -0xa40(%rbp)
movaps %xmm1, -0xa50(%rbp)
movaps %xmm0, -0xa60(%rbp)
movq -0x8(%rbp), %rax
leaq -0xe0(%rbp), %rdi
movq %rdi, 0x30(%rax)
callq 0x3160
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0xa6c(%rbp)
subl $0xffffff00, %eax       # imm = 0xFFFFFF00
je 0xe667
jmp 0xe621
movl -0xa6c(%rbp), %eax
testl %eax, %eax
jne 0xe692
jmp 0xe62d
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rsi
addq $0xa0, %rsi
callq 0x9420
movq -0x8(%rbp), %rdi
movq -0xa68(%rbp), %rsi
callq 0x6640
movq -0x8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6670
jmp 0xe6ea
movq -0x8(%rbp), %rdi
callq 0x93f0
movq -0x9c8(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4c90
jmp 0xe6ea
movq -0x8(%rbp), %rdi
leaq -0x9f8(%rbp), %rsi
movl $0x918, %edx            # imm = 0x918
callq 0x31e0
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
leaq -0xa30(%rbp), %rsi
movl $0x30, %edx
callq 0x31e0
movq -0x8(%rbp), %rax
movq 0x68(%rax), %rdi
leaq -0xa60(%rbp), %rsi
movl $0x30, %edx
callq 0x31e0
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
movslq -0xc(%rbp), %rsi
callq 0x4c90
addq $0xa70, %rsp            # imm = 0xA70
popq %rbp
retq
nopw %cs:(%rax,%rax)