// File: /workspace/github_c_makefile_star2_O1/creationix[P]color-control/src/libs/color-control.c
// Function: eval
uint32_t eval(vm_t* vm) {
  opcode_t op = *(vm->pc)++;
  // printf("%02x - %08x %08x %08x %08x %08x %08x %08x %08x\n", op,
  //   vm->vars[0], vm->vars[1], vm->vars[2], vm->vars[3],
  //   vm->vars[4], vm->vars[5], vm->vars[6], vm->vars[7]);
  // If the opcode is less than 128, it's a literal unsigned integer
  if (op < 128) return op;

  // Everything else needs to be switched based on it's code.
  switch (op) {
    // Handle the larger number literals (these consume 2-5 bytes)
    case UINT8:  return (vm->pc) += 1,  *(vm->pc - 1);
    case UINT16: return (vm->pc) += 2, (*(vm->pc - 2) << 8)  |  *(vm->pc - 1);
    case UINT24: return (vm->pc) += 3, (*(vm->pc - 3) << 16) | (*(vm->pc - 2) << 8)  |  *(vm->pc - 1);
    case UINT32: return (vm->pc) += 4, (*(vm->pc - 4) << 24) | (*(vm->pc - 3) << 16) | (*(vm->pc - 2) << 8) | *(vm->pc - 1);
    // Handle Arithmetic Operations
    case ADD: return eval(vm) + eval(vm);
    case SUB: return eval(vm) - eval(vm);
    case MUL: return eval(vm) * eval(vm);
    case DIV: return eval(vm) / eval(vm);
    case MOD: return eval(vm) % eval(vm);
    // Handle Comparision Operations
    case GT: return eval(vm) > eval(vm);
    case LT: return eval(vm) < eval(vm);
    case GTE: return eval(vm) >= eval(vm);
    case LTE: return eval(vm) >= eval(vm);
    case EQ: return eval(vm) == eval(vm);
    case NEQ: return eval(vm) != eval(vm);
    // Handle Logical Operations
    case AND: return eval(vm) && eval(vm);
    case OR: return eval(vm) || eval(vm);
    case NOT: return !eval(vm);

    // Handle variable reads/writes
    case GET0: case GET1: case GET2: case GET3:
    case GET4: case GET5: case GET6: case GET7:
      // printf("GET=%d\n", op - GET0);
      return vm->vars[op - GET0];
    case SET0: case SET1: case SET2: case SET3:
    case SET4: case SET5: case SET6: case SET7:
      // printf("SET=%d\n", op - SET0);
      return vm->vars[op - SET0] = eval(vm);
    // Handle variable loops
    case FOR0: case FOR1: case FOR2: case FOR3:
    case FOR4: case FOR5: case FOR6: case FOR7:
      return eval_for(op - FOR0, vm);

    // Handle other control-flow operations
    case WHILE: return eval_while(vm);
    case IF: return eval_if(vm);
    case DO: return eval_do(vm);

    case HUE: return eval_hue(vm);
    case RGB: return eval_rgb(vm);
    case MIX: return eval_mix(vm);
    case RAND: return eval_rand(vm);
    case SRAND: return eval_srand(vm);

    case WRITE: return eval_write(vm);
    case FILL: return eval_fill(vm);
    case FADE: return eval_fade(vm);

    case DELAY: return eval_delay(vm);
    case UPDATE: return eval_update(vm);
    case PINA: case PINB: return eval_pin(vm, op - PINA);

    case END:
      vm->on_error(op, "Illegal opcode");
  }
  vm->on_error(op, "Unknown opcode");
  return -1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r14
xorl %r12d, %r12d
leaq 0xda0(%rip), %rbx       # 0x2004
movq 0x58(%r14), %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x58(%r14)
movzbl (%rax), %r15d
testb %r15b, %r15b
jns 0x1616
leal -0x80(%r15), %ecx
cmpl $0x39, %ecx
ja 0x138a
movslq (%rbx,%rcx,4), %rcx
addq %rbx, %rcx
jmpq *%rcx
movq %r14, %rdi
callq 0x124c
addl %eax, %r12d
jmp 0x1264
movq %r14, %rdi
callq 0x124c
addl $0xffffff66, %r15d      # imm = 0xFFFFFF66
movl %eax, 0x38(%r14,%r15,4)
addl %eax, %r12d
jmp 0x1619
addl $0xffffff6e, %r15d      # imm = 0xFFFFFF6E
movl 0x38(%r14,%r15,4), %r15d
jmp 0x1616
movl %r12d, 0x4(%rsp)
addb $0x5e, %r15b
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
movl %eax, %r12d
movq %r14, %rdi
callq 0x124c
movl %eax, %r13d
movq 0x58(%r14), %rcx
movl %ebp, %eax
subl %r12d, %eax
jbe 0x130e
xorl %edx, %edx
divl %r13d
addl %edx, %r12d
negl %r13d
jmp 0x131b
movl %r12d, %eax
subl %ebp, %eax
xorl %edx, %edx
divl %r13d
subl %edx, %r12d
movzbl %r15b, %ebx
addl %r13d, %r12d
movl %ebp, 0x38(%r14,%rbx,4)
movq %rcx, 0x58(%r14)
movq %r14, %rdi
movq %rcx, %r15
callq 0x124c
movq %r15, %rcx
addl %r13d, %ebp
cmpl %ebp, %r12d
jne 0x1322
movl %eax, %r15d
movl 0x4(%rsp), %r12d
jmp 0x1616
addb $0x48, %r15b
movzbl %r15b, %esi
movq %r14, %rdi
callq 0x191e
jmp 0x1613
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %eax, %ebp
jmp 0x1595
leaq 0xe51(%rip), %rsi       # 0x21d4
movl %r15d, %edi
callq *0x10(%r14)
leaq 0xe52(%rip), %rsi       # 0x21e3
movl %r15d, %edi
callq *0x10(%r14)
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
jmp 0x1616
movq %r14, %rdi
callq 0x162b
jmp 0x1613
movq %r14, %rdi
callq 0x166c
jmp 0x1613
movq %r14, %rdi
callq 0x17e3
jmp 0x1613
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %ebp, %eax
jmp 0x14af
movq %r14, %rdi
callq 0x124c
cmpl $0x1, %eax
jmp 0x14af
movq %r14, %rdi
callq 0x1827
jmp 0x1613
leaq 0x5(%rax), %rcx
movq %rcx, 0x58(%r14)
movl 0x1(%rax), %r15d
bswapl %r15d
jmp 0x1616
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
movl %eax, %ecx
movl %ebp, %eax
xorl %edx, %edx
divl %ecx
addl %edx, %r12d
jmp 0x1619
movq %r14, %rdi
callq 0x124c
testl %eax, %eax
jne 0x158a
jmp 0x14dd
leaq 0x4(%rax), %rcx
movq %rcx, 0x58(%r14)
movzbl 0x1(%rax), %ecx
shll $0x10, %ecx
movzbl 0x2(%rax), %edx
shll $0x8, %edx
orl %ecx, %edx
movzbl 0x3(%rax), %r15d
orl %edx, %r15d
jmp 0x1616
leaq 0x2(%rax), %rcx
movq %rcx, 0x58(%r14)
movzbl 0x1(%rax), %r15d
jmp 0x1616
leaq 0x3(%rax), %rcx
movq %rcx, 0x58(%r14)
movzwl 0x1(%rax), %eax
rolw $0x8, %ax
movzwl %ax, %r15d
jmp 0x1616
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %eax, %ebp
adcl $0x0, %r12d
jmp 0x1619
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
xorl %ecx, %ecx
cmpl %eax, %ebp
setne %cl
jmp 0x15b4
leaq 0x20(%r14), %rdi
callq *(%r14)
xorl %r15d, %r15d
jmp 0x1616
movq %r14, %rdi
callq 0x185f
jmp 0x1613
movq %r14, %rdi
callq 0x168b
jmp 0x1613
movq %r14, %rdi
callq 0x1891
jmp 0x1613
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movl %eax, %edi
callq *0x18(%r14)
jmp 0x1606
movq %r14, %rdi
callq 0x124c
movl %eax, 0x2bd1(%rip)      # 0x4100
movl $0xdeadbeef, 0x2b47(%rip) # imm = 0xDEADBEEF
jmp 0x12b4
movq 0x58(%r14), %rax
xorl %r15d, %r15d
cmpb $-0x53, (%rax)
je 0x155b
movq %r14, %rdi
callq 0x124c
movl %eax, %r15d
movq 0x58(%r14), %rax
jmp 0x1545
incq %rax
movq %rax, 0x58(%r14)
jmp 0x1616
movq %r14, %rdi
callq 0x1726
jmp 0x1613
movq %r14, %rdi
callq 0x124c
movl $0x1, %r15d
testl %eax, %eax
jne 0x1616
movq %r14, %rdi
callq 0x124c
cmpl $0x1, %eax
sbbl $-0x1, %r12d
jmp 0x1619
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
xorl %ecx, %ecx
cmpl %eax, %ebp
sete %cl
addl %ecx, %r12d
jmp 0x1619
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
movl %eax, %ecx
movl %ebp, %eax
xorl %edx, %edx
divl %ecx
jmp 0x12b4
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
imull %ebp, %eax
jmp 0x12b4
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
subl %eax, %ebp
addl %ebp, %r12d
jmp 0x1619
movq %r14, %rdi
callq 0x175d
movl %eax, %r15d
addl %r15d, %r12d
movl %r12d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq