// File: rofl0r[P]ascc/cs_parser.cpp
// Function: check_operator_valid_for_type(int*, int, int)
int check_operator_valid_for_type(int *vcpuOpPtr, int type1, int type2) {
  int NULL_TYPE = STYPE_POINTER | sym.nullSym;
  int vcpuOp = *vcpuOpPtr;

  int isError = 0;
  // it's allowed to add or subtract from a pointer to an integral type.
  if (is_int(type1) && (type2 & STYPE_POINTER)
     && (vcpuOp == SCMD_ADDREG || vcpuOp == SCMD_SUBREG)
     && is_integral_type(type2 & ~STYPE_POINTER))
      return 0;
  if ((type1 == sym.normalFloatSym) || (type2 == sym.normalFloatSym)) {
    // some operators not valid on floats
    int changeOpTo = vcpuOp;
    switch (vcpuOp) {
    case SCMD_ISEQUAL: // == and != same as integer versions
    case SCMD_NOTEQUAL:
      break;
    case SCMD_ADD:
      changeOpTo = SCMD_FADD;
      break;
    case SCMD_SUB:
      changeOpTo = SCMD_FSUB;
      break;
    case SCMD_ADDREG:
      changeOpTo = SCMD_FADDREG;
      break;
    case SCMD_SUBREG:
      changeOpTo = SCMD_FSUBREG;
      break;
    case SCMD_MULREG:
      changeOpTo = SCMD_FMULREG;
      break;
    case SCMD_DIVREG:
      changeOpTo = SCMD_FDIVREG;
      break;
    case SCMD_GREATER:
      changeOpTo = SCMD_FGREATER;
      break;
    case SCMD_LESSTHAN:
      changeOpTo = SCMD_FLESSTHAN;
      break;
    case SCMD_GTE:
      changeOpTo = SCMD_FGTE;
      break;
    case SCMD_LTE:
      changeOpTo = SCMD_FLTE;
      break;
    default:
      isError = 1;
    }
    vcpuOp = changeOpTo;
    *vcpuOpPtr = changeOpTo;
  }

  if (is_any_type_of_string(type1) && is_any_type_of_string(type2)) {
    if (vcpuOp == SCMD_ISEQUAL) {
      *vcpuOpPtr = SCMD_STRINGSEQUAL;
      return 0;
    }
    else if (vcpuOp == SCMD_NOTEQUAL) {
      *vcpuOpPtr = SCMD_STRINGSNOTEQ;
      return 0;
    }
  }

  if ((type1 & STYPE_POINTER) || (is_string(type1))) {
    isError = 1;
  }
  if (type2) {
    if ((type2 & STYPE_POINTER) || (is_string(type2))) {
      isError = 1;
    }
    if ((vcpuOp == SCMD_ISEQUAL) || (vcpuOp == SCMD_NOTEQUAL)) {
      // pointers can be compared to each other
      // (except strings)
      if (!is_string(type1))
        isError = 0;
    }
  }

  if (isError) {
    cc_error("Operator cannot be applied to this type");
    return -1;
  }
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
leaq 0x38347(%rip), %rax     # 0x42870
movl 0x1c(%rax), %eax
orl $0x40000000, %eax       # imm = 0x40000000
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x14(%rbp), %edi
callq 0xa740
cmpl $0x0, %eax
je 0xa589
movl -0x18(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
je 0xa589
cmpl $0xb, -0x20(%rbp)
je 0xa56a
cmpl $0xc, -0x20(%rbp)
jne 0xa589
movl -0x18(%rbp), %edi
andl $0xbfffffff, %edi       # imm = 0xBFFFFFFF
callq 0xa760
cmpl $0x0, %eax
je 0xa589
movl $0x0, -0x4(%rbp)
jmp 0xa72d
movl -0x14(%rbp), %eax
leaq 0x382dd(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
je 0xa5ab
movl -0x18(%rbp), %eax
leaq 0x382ce(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
jne 0xa647
movl -0x20(%rbp), %eax
movl %eax, -0x28(%rbp)
movl -0x20(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0x13, %eax
ja 0xa631
movq -0x30(%rbp), %rax
leaq 0x272e8(%rip), %rcx     # 0x318b4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0xa638
movl $0x35, -0x28(%rbp)
jmp 0xa638
movl $0x36, -0x28(%rbp)
jmp 0xa638
movl $0x39, -0x28(%rbp)
jmp 0xa638
movl $0x3a, -0x28(%rbp)
jmp 0xa638
movl $0x37, -0x28(%rbp)
jmp 0xa638
movl $0x38, -0x28(%rbp)
jmp 0xa638
movl $0x3b, -0x28(%rbp)
jmp 0xa638
movl $0x3c, -0x28(%rbp)
jmp 0xa638
movl $0x3d, -0x28(%rbp)
jmp 0xa638
movl $0x3e, -0x28(%rbp)
jmp 0xa638
movl $0x1, -0x24(%rbp)
movl -0x28(%rbp), %eax
movl %eax, -0x20(%rbp)
movl -0x28(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
movl -0x14(%rbp), %edi
callq 0x83d0
cmpl $0x0, %eax
je 0xa69d
movl -0x18(%rbp), %edi
callq 0x83d0
cmpl $0x0, %eax
je 0xa69d
cmpl $0xf, -0x20(%rbp)
jne 0xa67d
movq -0x10(%rbp), %rax
movl $0x41, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0xa72d
cmpl $0x10, -0x20(%rbp)
jne 0xa699
movq -0x10(%rbp), %rax
movl $0x42, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0xa72d
jmp 0xa69b
jmp 0xa69d
movl -0x14(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
jne 0xa6b7
movl -0x14(%rbp), %edi
callq 0xa470
cmpl $0x0, %eax
je 0xa6be
movl $0x1, -0x24(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0xa709
movl -0x18(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
jne 0xa6de
movl -0x18(%rbp), %edi
callq 0xa470
cmpl $0x0, %eax
je 0xa6e5
movl $0x1, -0x24(%rbp)
cmpl $0xf, -0x20(%rbp)
je 0xa6f1
cmpl $0x10, -0x20(%rbp)
jne 0xa707
movl -0x14(%rbp), %edi
callq 0xa470
cmpl $0x0, %eax
jne 0xa705
movl $0x0, -0x24(%rbp)
jmp 0xa707
jmp 0xa709
cmpl $0x0, -0x24(%rbp)
je 0xa726
leaq 0x27894(%rip), %rdi     # 0x31faa
movb $0x0, %al
callq 0x1bac0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa72d
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)