// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x58(%rcx)
movzbl (%rax), %eax
movl %eax, -0x14(%rbp)
cmpl $0x80, -0x14(%rbp)
jae 0x1209
movl -0x14(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movl -0x14(%rbp), %eax
addl $-0x80, %eax
movl %eax, %ecx
movq %rcx, -0x20(%rbp)
subl $0x39, %eax
ja 0x16ce
movq -0x20(%rbp), %rax
leaq 0x1ddb(%rip), %rcx      # 0x3004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movzbl -0x1(%rax), %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rcx
addq $0x2, %rcx
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movzbl -0x2(%rax), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rcx
addq $0x3, %rcx
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movzbl -0x3(%rax), %eax
shll $0x10, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x2(%rcx), %ecx
shll $0x8, %ecx
orl %ecx, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rcx
addq $0x4, %rcx
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movzbl -0x4(%rax), %eax
shll $0x18, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x3(%rcx), %ecx
shll $0x10, %ecx
orl %ecx, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x2(%rcx), %ecx
shll $0x8, %ecx
orl %ecx, %eax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x24(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x24(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x28(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x2c(%rbp), %eax
imull %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x30(%rbp), %eax
xorl %edx, %edx
divl %ecx
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x34(%rbp), %eax
xorl %edx, %edx
divl %ecx
movl %edx, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x38(%rbp), %eax
cmpl %ecx, %eax
seta %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x3c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x3c(%rbp), %eax
cmpl %ecx, %eax
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x40(%rbp), %eax
cmpl %ecx, %eax
setae %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x44(%rbp), %eax
cmpl %ecx, %eax
setae %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x48(%rbp), %eax
cmpl %ecx, %eax
sete %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, -0x4c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movl -0x4c(%rbp), %eax
cmpl %ecx, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x4d(%rbp)
je 0x1510
movq -0x10(%rbp), %rdi
callq 0x11d0
cmpl $0x0, %eax
setne %al
movb %al, -0x4d(%rbp)
movb -0x4d(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x4e(%rbp)
jne 0x1547
movq -0x10(%rbp), %rdi
callq 0x11d0
cmpl $0x0, %eax
setne %al
movb %al, -0x4e(%rbp)
movb -0x4e(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rax
movl -0x14(%rbp), %ecx
subl $0x92, %ecx
movl %ecx, %ecx
movl 0x38(%rax,%rcx,4), %eax
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x11d0
movq -0x10(%rbp), %rcx
movl -0x14(%rbp), %edx
subl $0x9a, %edx
movl %edx, %edx
movl %eax, 0x38(%rcx,%rdx,4)
movl %eax, -0x4(%rbp)
jmp 0x16e9
movl -0x14(%rbp), %eax
subl $0xa2, %eax
movq -0x10(%rbp), %rsi
movzbl %al, %edi
callq 0x1700
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x17d0
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1830
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1880
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x18d0
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1a10
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1a70
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1b30
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1ba0
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1be0
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1c80
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1d10
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1e30
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
callq 0x1e60
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %eax
subl $0xb8, %eax
movzbl %al, %esi
callq 0x1e90
movl %eax, -0x4(%rbp)
jmp 0x16e9
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl -0x14(%rbp), %edi
leaq 0x1b08(%rip), %rsi      # 0x31d4
callq *%rax
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl -0x14(%rbp), %edi
leaq 0x1b03(%rip), %rsi      # 0x31e3
callq *%rax
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)