// File: /workspace/github_c_makefile_star2_O0/vtereshkov[P]umka-lang/src/umka_const.c
// Function: constBinary
void constBinary(const Consts *consts, Const *lhs, const Const *rhs, TokenKind tokKind, TypeKind typeKind)
{
    if (typeKind == TYPE_PTR)
        switch (tokKind)
        {
            case TOK_EQEQ:      lhs->intVal = lhs->ptrVal == rhs->ptrVal; break;
            case TOK_NOTEQ:     lhs->intVal = lhs->ptrVal != rhs->ptrVal; break;

            default:            consts->error->handler(consts->error->context, "Illegal operator");
        }
    else if (typeKind == TYPE_STR)
        switch (tokKind)
        {
            case TOK_PLUS:      strcat((char *)lhs->ptrVal, (char *)rhs->ptrVal); break;

            case TOK_EQEQ:      lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) == 0; break;
            case TOK_NOTEQ:     lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) != 0; break;
            case TOK_GREATER:   lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) >  0; break;
            case TOK_LESS:      lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) <  0; break;
            case TOK_GREATEREQ: lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) >= 0; break;
            case TOK_LESSEQ:    lhs->intVal = strcmp((char *)lhs->ptrVal, (char *)rhs->ptrVal) <= 0; break;

            default:            consts->error->handler(consts->error->context, "Illegal operator");
        }
    else if (typeKind == TYPE_REAL || typeKind == TYPE_REAL32)
        switch (tokKind)
        {
            case TOK_PLUS:  lhs->realVal += rhs->realVal; break;
            case TOK_MINUS: lhs->realVal -= rhs->realVal; break;
            case TOK_MUL:   lhs->realVal *= rhs->realVal; break;
            case TOK_DIV:
            {
                if (rhs->realVal == 0)
                    consts->error->handler(consts->error->context, "Division by zero");
                lhs->realVal /= rhs->realVal;
                break;
            }
            case TOK_MOD:
            {
                if (rhs->realVal == 0)
                    consts->error->handler(consts->error->context, "Division by zero");
                lhs->realVal = fmod(lhs->realVal, rhs->realVal);
                break;
            }

            case TOK_EQEQ:      lhs->intVal = lhs->realVal == rhs->realVal; break;
            case TOK_NOTEQ:     lhs->intVal = lhs->realVal != rhs->realVal; break;
            case TOK_GREATER:   lhs->intVal = lhs->realVal >  rhs->realVal; break;
            case TOK_LESS:      lhs->intVal = lhs->realVal <  rhs->realVal; break;
            case TOK_GREATEREQ: lhs->intVal = lhs->realVal >= rhs->realVal; break;
            case TOK_LESSEQ:    lhs->intVal = lhs->realVal <= rhs->realVal; break;

            default:            consts->error->handler(consts->error->context, "Illegal operator");
        }
    else
        switch (tokKind)
        {
            case TOK_PLUS:  lhs->intVal += rhs->intVal; break;
            case TOK_MINUS: lhs->intVal -= rhs->intVal; break;
            case TOK_MUL:   lhs->intVal *= rhs->intVal; break;
            case TOK_DIV:
            {
                if (rhs->intVal == 0)
                    consts->error->handler(consts->error->context, "Division by zero");
                if (lhs->intVal == LLONG_MIN && rhs->intVal == -1)
                    consts->error->handler(consts->error->context, "Overflow of int");
                lhs->intVal /= rhs->intVal;
                break;
            }
            case TOK_MOD:
            {
                if (rhs->intVal == 0)
                    consts->error->handler(consts->error->context, "Division by zero");
                if (lhs->intVal == LLONG_MIN && rhs->intVal == -1)
                    consts->error->handler(consts->error->context, "Overflow of int");
                lhs->intVal %= rhs->intVal;
                break;
            }

            case TOK_SHL:   lhs->intVal <<= rhs->intVal; break;
            case TOK_SHR:   lhs->intVal >>= rhs->intVal; break;
            case TOK_AND:   lhs->intVal &= rhs->intVal; break;
            case TOK_OR:    lhs->intVal |= rhs->intVal; break;
            case TOK_XOR:   lhs->intVal ^= rhs->intVal; break;

            case TOK_EQEQ:      lhs->intVal = lhs->intVal == rhs->intVal; break;
            case TOK_NOTEQ:     lhs->intVal = lhs->intVal != rhs->intVal; break;
            case TOK_GREATER:   lhs->intVal = lhs->intVal >  rhs->intVal; break;
            case TOK_LESS:      lhs->intVal = lhs->intVal <  rhs->intVal; break;
            case TOK_GREATEREQ: lhs->intVal = lhs->intVal >= rhs->intVal; break;
            case TOK_LESSEQ:    lhs->intVal = lhs->intVal <= rhs->intVal; break;

            default:            consts->error->handler(consts->error->context, "Illegal operator");
        }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl %r8d, -0x20(%rbp)
cmpl $0x10, -0x20(%rbp)
jne 0x8cd5
movl -0x1c(%rbp), %eax
movl %eax, -0x24(%rbp)
subl $0x2e, %eax
je 0x8c6c
jmp 0x8c62
movl -0x24(%rbp), %eax
subl $0x34, %eax
je 0x8c8e
jmp 0x8cb0
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
sete %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8cd0
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8cd0
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cf33e(%rip), %rsi    # 0x1d800a
movb $0x0, %al
callq *%rcx
jmp 0x938a
cmpl $0x14, -0x20(%rbp)
jne 0x8e4a
movl -0x1c(%rbp), %eax
addl $-0x16, %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0x20, %eax
ja 0x8e25
movq -0x30(%rbp), %rax
leaq 0x1cf121(%rip), %rcx    # 0x1d7e20
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3370
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
sete %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
setg %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
setl %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
setge %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x3220
cmpl $0x0, %eax
setle %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e45
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cf1c9(%rip), %rsi    # 0x1d800a
movb $0x0, %al
callq *%rcx
jmp 0x9388
cmpl $0xf, -0x20(%rbp)
je 0x8e5a
cmpl $0xe, -0x20(%rbp)
jne 0x908f
movl -0x1c(%rbp), %eax
addl $-0x16, %eax
movl %eax, %ecx
movq %rcx, -0x38(%rbp)
subl $0x20, %eax
ja 0x906a
movq -0x38(%rbp), %rax
leaq 0x1cef22(%rip), %rcx    # 0x1d7d9c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
movq -0x10(%rbp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
jmp 0x908a
movq -0x18(%rbp), %rax
movsd (%rax), %xmm1
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, (%rax)
jmp 0x908a
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
movq -0x10(%rbp), %rax
mulsd (%rax), %xmm0
movsd %xmm0, (%rax)
jmp 0x908a
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x8f05
jp 0x8f05
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cf11a(%rip), %rsi    # 0x1d801b
movb $0x0, %al
callq *%rcx
movq -0x18(%rbp), %rax
movsd (%rax), %xmm1
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, (%rax)
jmp 0x908a
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x8f55
jp 0x8f55
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cf0ca(%rip), %rsi    # 0x1d801b
movb $0x0, %al
callq *%rcx
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movq -0x18(%rbp), %rax
movsd (%rax), %xmm1
callq 0x31e0
movq -0x10(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movq -0x18(%rbp), %rax
ucomisd (%rax), %xmm0
sete %al
setnp %cl
andb %cl, %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movq -0x18(%rbp), %rax
ucomisd (%rax), %xmm0
setne %al
setp %cl
orb %cl, %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movq -0x18(%rbp), %rax
ucomisd (%rax), %xmm0
seta %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm1
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
seta %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm0
movq -0x18(%rbp), %rax
ucomisd (%rax), %xmm0
setae %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x10(%rbp), %rax
movsd (%rax), %xmm1
movq -0x18(%rbp), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
setae %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x908a
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cef84(%rip), %rsi    # 0x1d800a
movb $0x0, %al
callq *%rcx
jmp 0x9386
movl -0x1c(%rbp), %eax
addl $-0x16, %eax
movl %eax, %ecx
movq %rcx, -0x40(%rbp)
subl $0x20, %eax
ja 0x9364
movq -0x40(%rbp), %rax
leaq 0x1cec69(%rip), %rcx    # 0x1d7d18
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rdx
movq -0x10(%rbp), %rax
movq (%rax), %rcx
subq %rdx, %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
imulq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x9128
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1ceef7(%rip), %rsi    # 0x1d801b
movb $0x0, %al
callq *%rcx
movq -0x10(%rbp), %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
cmpq %rcx, (%rax)
jne 0x9165
movq -0x18(%rbp), %rax
cmpq $-0x1, (%rax)
jne 0x9165
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1ceecb(%rip), %rsi    # 0x1d802c
movb $0x0, %al
callq *%rcx
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq %rax, -0x48(%rbp)
movq (%rax), %rax
cqto
idivq %rcx
movq %rax, %rcx
movq -0x48(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x91b5
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cee6a(%rip), %rsi    # 0x1d801b
movb $0x0, %al
callq *%rcx
movq -0x10(%rbp), %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
cmpq %rcx, (%rax)
jne 0x91f2
movq -0x18(%rbp), %rax
cmpq $-0x1, (%rax)
jne 0x91f2
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cee3e(%rip), %rsi    # 0x1d802c
movb $0x0, %al
callq *%rcx
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
movq (%rax), %rax
cqto
idivq %rcx
movq -0x50(%rbp), %rax
movq %rdx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq (%rax), %rdx
shlq %cl, %rdx
movq %rdx, %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq (%rax), %rdx
sarq %cl, %rdx
movq %rdx, %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
andq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
orq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
xorq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
sete %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setg %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setl %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setge %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setle %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x9384
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x20(%rax), %rdi
leaq 0x1cec8a(%rip), %rsi    # 0x1d800a
movb $0x0, %al
callq *%rcx
jmp 0x9386
jmp 0x9388
jmp 0x938a
addq $0x50, %rsp
popq %rbp
retq