// File: /workspace/github_c_makefile_star2_O3/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 0x58(%rdi), %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x58(%rdi)
movb (%rax), %r13b
xorl %r12d, %r12d
testb %r13b, %r13b
js 0x1287
movzbl %r13b, %eax
addl %eax, %r12d
movl %r12d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rdi, %r14
xorl %r12d, %r12d
leaq 0xd70(%rip), %rbx       # 0x2004
movzbl %r13b, %r15d
leal -0x80(%r15), %edx
cmpl $0x39, %edx
ja 0x1405
movslq (%rbx,%rdx,4), %rdx
addq %rbx, %rdx
jmpq *%rdx
movq %r14, %rdi
callq 0x124c
addl %eax, %r12d
movq 0x58(%r14), %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x58(%r14)
movb (%rax), %r13b
testb %r13b, %r13b
js 0x1294
jmp 0x126e
movl %r12d, 0x4(%rsp)
addb $0x5e, %r13b
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
movl %eax, %r15d
movq %r14, %rdi
callq 0x124c
movl %eax, %r12d
movq 0x58(%r14), %rbx
movl %ebp, %eax
subl %r15d, %eax
jbe 0x133b
xorl %edx, %edx
divl %r12d
addl %edx, %r15d
negl %r12d
jmp 0x1348
movq %r14, %rdi
callq 0x124c
movl $0xffffff66, %ecx       # imm = 0xFFFFFF66
addl %ecx, %r15d
movl %eax, 0x38(%r14,%r15,4)
jmp 0x1272
addl $0xffffff6e, %r15d      # imm = 0xFFFFFF6E
movl 0x38(%r14,%r15,4), %eax
jmp 0x1272
movl %r15d, %eax
subl %ebp, %eax
xorl %edx, %edx
divl %r12d
subl %edx, %r15d
movzbl %r13b, %r13d
addl %r12d, %r15d
movl %ebp, 0x38(%r14,%r13,4)
movq %rbx, 0x58(%r14)
movq %r14, %rdi
callq 0x124c
addl %r12d, %ebp
cmpl %ebp, %r15d
jne 0x134f
movl 0x4(%rsp), %r12d
jmp 0x1272
addb $0x48, %r13b
movzbl %r13b, %esi
movq %r14, %rdi
callq 0x1935
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %eax, %ebp
jmp 0x158e
movq %r14, %rdi
callq 0x183e
jmp 0x1272
movq %r14, %rdi
callq 0x1683
jmp 0x1272
leaq 0x20(%r14), %rdi
callq *(%r14)
jmp 0x1597
movq %r14, %rdi
callq 0x1774
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ecx
movl $0x1, %eax
testl %ecx, %ecx
jne 0x1272
jmp 0x1583
leaq 0xdde(%rip), %rsi       # 0x21d4
movl $0xad, %r15d
movl $0xad, %edi
callq *0x10(%r14)
leaq 0xdd7(%rip), %rsi       # 0x21e3
movl %r15d, %edi
callq *0x10(%r14)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
xorl %ecx, %ecx
cmpl %eax, %ebp
sete %cl
jmp 0x151a
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 0x1275
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %eax, %ebp
jmp 0x1554
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 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
addl %r12d, %ebp
subl %eax, %ebp
movl %ebp, %r12d
jmp 0x1275
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), %eax
orl %edx, %eax
jmp 0x1272
leaq 0x5(%rax), %rcx
movq %rcx, 0x58(%r14)
movl 0x1(%rax), %eax
bswapl %eax
jmp 0x1272
leaq 0x3(%rax), %rcx
movq %rcx, 0x58(%r14)
movzwl 0x1(%rax), %eax
rolw $0x8, %ax
movzwl %ax, %eax
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
xorl %ecx, %ecx
cmpl %eax, %ebp
setne %cl
addl %ecx, %r12d
jmp 0x1275
leaq 0x2(%rax), %rcx
movq %rcx, 0x58(%r14)
movzbl 0x1(%rax), %eax
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
cmpl %ebp, %eax
jmp 0x1554
movq %r14, %rdi
callq 0x124c
cmpl $0x1, %eax
adcl $0x0, %r12d
jmp 0x1275
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movq %r14, %rdi
callq 0x124c
imull %ebp, %eax
jmp 0x1272
movq %r14, %rdi
callq 0x124c
testl %eax, %eax
je 0x1597
movq %r14, %rdi
callq 0x124c
cmpl $0x1, %eax
sbbl $-0x1, %r12d
jmp 0x1275
xorl %eax, %eax
jmp 0x1272
xorl %eax, %eax
cmpb $-0x53, (%rcx)
je 0x15b3
movq %r14, %rdi
callq 0x124c
movq 0x58(%r14), %rcx
jmp 0x15a0
incq %rcx
movq %rcx, 0x58(%r14)
jmp 0x1272
movq %r14, %rdi
callq 0x16a2
jmp 0x1272
movq %r14, %rdi
callq 0x17fa
jmp 0x1272
movq %r14, %rdi
callq 0x1642
jmp 0x1272
movq %r14, %rdi
callq 0x1876
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, %ebp
movl %eax, %edi
callq *0x18(%r14)
addl %ebp, %r12d
jmp 0x1275
movq %r14, %rdi
callq 0x173d
jmp 0x1272
movq %r14, %rdi
callq 0x124c
movl %eax, 0x2ada(%rip)      # 0x4100
movl $0xdeadbeef, 0x2a50(%rip) # imm = 0xDEADBEEF
jmp 0x1272
movq %r14, %rdi
callq 0x18a8
jmp 0x1272