// File: /workspace/github_c_makefile_star2_O2/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, %rbp
xorl %r12d, %r12d
leaq 0xe10(%rip), %r15       # 0x2004
movq 0x58(%rbp), %r14
leaq 0x1(%r14), %rax
movq %rax, 0x58(%rbp)
movzbl (%r14), %edx
testb %dl, %dl
jns 0x1840
leal -0x80(%rdx), %ecx
cmpl $0x39, %ecx
ja 0x135a
movslq (%r15,%rcx,4), %rcx
addq %r15, %rcx
jmpq *%rcx
movq %rbp, %rdi
callq 0x11dc
testl %eax, %eax
jne 0x11f4
jmp 0x17d6
movq %rbp, %rdi
callq 0x11dc
addl %eax, %r12d
jmp 0x11f4
movl %r12d, 0x4(%rsp)
addb $0x5e, %dl
movq %rdx, %rbx
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r14d
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r15d
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r12d
movq 0x58(%rbp), %r13
movl %r14d, %eax
subl %r15d, %eax
jbe 0x12b1
xorl %edx, %edx
divl %r12d
addl %edx, %r15d
negl %r12d
jmp 0x12bf
movq %rbp, %rdi
movq %rdx, %rbx
callq 0x11dc
movl $0xffffff66, %ecx       # imm = 0xFFFFFF66
addl %ebx, %ecx
movl %eax, 0x38(%rbp,%rcx,4)
addl %eax, %r12d
jmp 0x17d1
leal -0x92(%rdx), %eax
movl 0x38(%rbp,%rax,4), %edx
jmp 0x1840
movl %r15d, %eax
subl %r14d, %eax
xorl %edx, %edx
divl %r12d
subl %edx, %r15d
movzbl %bl, %ebx
addl %r12d, %r15d
movl %r14d, 0x38(%rbp,%rbx,4)
movq %r13, 0x58(%rbp)
movq %rbp, %rdi
callq 0x11dc
addl %r12d, %r14d
cmpl %r14d, %r15d
jne 0x12c5
movl %eax, %edx
movl 0x4(%rsp), %r12d
jmp 0x1840
addb $0x48, %dl
movq %rbp, %rdi
movq %rdx, %rbx
callq 0x11dc
movl %eax, %r14d
movq %rbp, %rdi
callq 0x11dc
xorl %r15d, %r15d
testl %eax, %eax
setne %r15b
movzbl %bl, %edi
movzbl %r14b, %esi
movl %r15d, %edx
callq *0x8(%rbp)
addl %r15d, %r12d
jmp 0x17d1
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
cmpl %eax, %ebx
jmp 0x1579
leaq 0x20(%rbp), %rdi
callq *(%rbp)
jmp 0x17de
leaq 0xe87(%rip), %rsi       # 0x21d4
movl $0xad, %edi
callq *0x10(%rbp)
movl $0xad, %edx
leaq 0xe82(%rip), %rsi       # 0x21e3
movl %edx, %edi
callq *0x10(%rbp)
pushq $-0x1
jmp 0x1568
movq %rbp, %rdi
callq 0x11dc
movl %eax, %edi
shrl $0x10, %edi
movq %rax, %rsi
movl %eax, %ecx
shrl $0x8, %ecx
xorl %edx, %edx
cmpq $0x17, %rdx
ja 0x13a0
movb %dil, 0x20(%rbp,%rdx)
movb %cl, 0x21(%rbp,%rdx)
movq %rsi, %rax
movb %al, 0x22(%rbp,%rdx)
addq $0x3, %rdx
jmp 0x1384
movq %rsi, %rdx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r14d
movq %rbp, %rdi
callq 0x11dc
movl %eax, %edx
cmpl $0x7, %r14d
ja 0x1840
movl %r14d, %eax
leaq (%rax,%rax,2), %rax
movl %edx, %ecx
shrl $0x10, %ecx
movb %cl, 0x20(%rbp,%rax)
movb %dh, 0x21(%rbp,%rax)
movb %dl, 0x22(%rbp,%rax)
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
cmpl $0x1, %eax
jmp 0x1491
movq %rbp, %rdi
callq 0x11dc
xorl %ecx, %ecx
movl $0x600, %esi            # imm = 0x600
xorl %edx, %edx
divl %esi
movl $0xff, %eax
cmpl $0x100, %edx            # imm = 0x100
jb 0x1836
cmpl $0x1ff, %edx            # imm = 0x1FF
ja 0x17e2
movl $0x1ff, %eax            # imm = 0x1FF
subl %edx, %eax
movl $0xff, %edx
jmp 0x1836
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
movq %rbx, %rdx
addl %r12d, %edx
subl %eax, %edx
jmp 0x1843
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
cmpl %eax, %ebx
jmp 0x1491
leaq 0x5(%r14), %rax
movq %rax, 0x58(%rbp)
movl 0x1(%r14), %edx
bswapl %edx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
cmpl %ebx, %eax
adcl $0x0, %r12d
jmp 0x17d1
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
xorl %ecx, %ecx
cmpl %eax, %ebx
sete %cl
jmp 0x15b9
movq %rbp, %rdi
callq 0x11dc
testl %eax, %eax
jne 0x156e
jmp 0x17de
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ecx
movl %ebx, %eax
xorl %edx, %edx
divl %ecx
movl %eax, %edx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ecx
movl %ebx, %eax
jmp 0x1630
leaq 0x4(%r14), %rax
movq %rax, 0x58(%rbp)
movzbl 0x1(%r14), %eax
shll $0x10, %eax
movzbl 0x2(%r14), %ecx
shll $0x8, %ecx
orl %eax, %ecx
movzbl 0x3(%r14), %edx
orl %ecx, %edx
jmp 0x1840
leaq 0x2(%r14), %rax
movq %rax, 0x58(%rbp)
movzbl 0x1(%r14), %edx
jmp 0x1840
leaq 0x3(%r14), %rax
movq %rax, 0x58(%rbp)
movzwl 0x1(%r14), %eax
rolw $0x8, %ax
movzwl %ax, %edx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
testl %eax, %eax
je 0x156e
pushq $0x1
popq %rdx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
cmpl $0x1, %eax
sbbl $-0x1, %r12d
jmp 0x17d1
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r14d
movq %rbp, %rdi
callq 0x11dc
movl %eax, %edx
imull %r14d, %edx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
xorl %ecx, %ecx
cmpl %eax, %ebx
setne %cl
addl %ecx, %r12d
jmp 0x17d1
incq %r14
xorl %ebx, %ebx
movq %r14, 0x58(%rbp)
movq %rbp, %rdi
callq 0x11dc
testl %eax, %eax
je 0x15e2
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
jmp 0x15c6
movq %rbp, %rdi
callq 0x1aa0
movq %rbx, %rdx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ecx
movl 0x2afe(%rip), %eax      # 0x4100
movl %eax, %edx
shll $0x7, %edx
shrl $0x19, %eax
movl 0x2a70(%rip), %esi      # 0x4080
addl %esi, %eax
xorl %edx, %eax
movl %eax, 0x2ae6(%rip)      # 0x4100
movl %esi, %edx
shll $0x7, %edx
shrl $0x19, %esi
addl $0xdeadbeef, %esi       # imm = 0xDEADBEEF
xorl %edx, %esi
movl %esi, 0x2a50(%rip)      # 0x4080
xorl %edx, %edx
divl %ecx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movzbl %al, %ebx
shll $0x10, %ebx
movq %rbp, %rdi
callq 0x11dc
shll $0x8, %eax
movzwl %ax, %r14d
orl %ebx, %r14d
movq %rbp, %rdi
callq 0x11dc
movzbl %al, %edx
addl %r12d, %edx
addl %r14d, %edx
jmp 0x1843
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
movl $0xff, %r8d
andl %r8d, %eax
movl $0x100, %ecx            # imm = 0x100
subl %eax, %ecx
incl %eax
movl %ebx, %edx
shrl $0x10, %edx
andl %r8d, %edx
imull %eax, %edx
movl %ebx, %esi
shrl $0x8, %esi
andl %r8d, %esi
imull %eax, %esi
movq %rbx, %r9
movl %ebx, %edi
andl %r8d, %edi
imull %eax, %edi
xorl %eax, %eax
cmpq $0x17, %rax
ja 0x16ec
movzbl 0x20(%rbp,%rax), %ebx
imull %ecx, %ebx
addl %edx, %ebx
movb %bh, 0x20(%rbp,%rax)
movzbl 0x21(%rbp,%rax), %ebx
imull %ecx, %ebx
addl %esi, %ebx
movb %bh, 0x21(%rbp,%rax)
movzbl 0x22(%rbp,%rax), %ebx
imull %ecx, %ebx
addl %edi, %ebx
movb %bh, 0x22(%rbp,%rax)
addq $0x3, %rax
jmp 0x16b6
movq %r9, %rdx
jmp 0x1840
xorl %edx, %edx
cmpb $-0x53, (%rax)
je 0x170b
movq %rbp, %rdi
callq 0x11dc
movl %eax, %edx
movq 0x58(%rbp), %rax
jmp 0x16f6
incq %rax
movq %rax, 0x58(%rbp)
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, 0x29db(%rip)      # 0x4100
movl $0xdeadbeef, 0x2951(%rip) # imm = 0xDEADBEEF
jmp 0x129a
movq %rbp, %rdi
callq 0x11dc
movl %eax, %r14d
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movq %rbp, %rdi
callq 0x11dc
movl $0xff, %ecx
andl %ecx, %eax
leal 0x1(%rax), %edx
xorl %ecx, %eax
movl %r14d, %edi
shrl $0x10, %edi
andl %ecx, %edi
imull %eax, %edi
movl %ebx, %esi
shrl $0x10, %esi
andl %ecx, %esi
imull %edx, %esi
addl %edi, %esi
shll $0x8, %esi
andl $0x3ff0000, %esi        # imm = 0x3FF0000
movl %r14d, %edi
shrl $0x8, %edi
andl %ecx, %edi
imull %eax, %edi
movl %ebx, %r8d
shrl $0x8, %r8d
andl %ecx, %r8d
imull %edx, %r8d
addl %edi, %r8d
andl $0x3ff00, %r8d          # imm = 0x3FF00
andl %ecx, %r14d
imull %eax, %r14d
andl %ecx, %ebx
imull %edx, %ebx
movq %rbx, %rdx
addl %r14d, %edx
shrl $0x8, %edx
orl %r8d, %edx
orl %esi, %edx
jmp 0x1840
movq %rbp, %rdi
callq 0x11dc
movl %eax, %ebx
movl %eax, %edi
callq *0x18(%rbp)
addl %ebx, %r12d
movl %r12d, %edx
jmp 0x1843
movq %rbp, %rdi
callq 0x1aa0
xorl %edx, %edx
jmp 0x1840
cmpl $0x2ff, %edx            # imm = 0x2FF
ja 0x17fb
movl %edx, %ecx
addl $0xfffffe00, %ecx       # imm = 0xFFFFFE00
movl $0xff, %edx
xorl %eax, %eax
jmp 0x1836
cmpl $0x3ff, %edx            # imm = 0x3FF
ja 0x1816
movq %rdx, %rax
movl $0x3ff, %edx            # imm = 0x3FF
subl %eax, %edx
movl $0xff, %ecx
xorl %eax, %eax
jmp 0x1836
cmpl $0x4ff, %edx            # imm = 0x4FF
ja 0x182d
addl $0xfffffc00, %edx       # imm = 0xFFFFFC00
movl $0xff, %ecx
movl %edx, %eax
jmp 0x1834
movl $0x5ff, %ecx            # imm = 0x5FF
subl %edx, %ecx
xorl %edx, %edx
shll $0x10, %eax
orl %ecx, %eax
shll $0x8, %edx
orl %eax, %edx
addl %r12d, %edx
movl %edx, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq