// File: /workspace/github_cpp_makefile_star2_O1/akshayrajput[P]ARMV8_Simulator/./CMP.cpp
// Function: CMP()
void CMP()
{
    printf("[log] - CMP instruction\n");
    int sf = IR.getLowerData() & 0x80000000;
    int op = IR.getLowerData() & 0x40000000;
    int S = IR.getLowerData() & 0x20000000;
    int shift = (IR.getLowerData()  & 0x00c00000) >> 22;
    int imm12 = (IR.getLowerData()  & 0x003ffc00) >> 10;
    int mod = (IR.getLowerData()  & 0x1f000000) >> 24;
    int rn = (IR.getLowerData()  & 0x000003e0) >> 5;
    int rd = IR.getLowerData()  & 0x0000001f;

    if(mod == 17)   //immediate
    {
	printf("[log] - CMP instruction immediate\n");
        uint64_t imm = imm12;
        if(shift == 1)
        {
            imm = imm12 << 12;
        }
        
        if(sf)
        {
            uint64_t dat = R[rn].getData();
            if((dat > 0 && imm < 0 && (dat-imm) < 0) || (dat < 0 && imm > 0 && (dat - imm) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (dat <imm);
            if(CFLAG)
		    printf("Carry flag set\n");
            NFLAG = (dat < imm);
            if(NFLAG)
		    printf("Negative flag set\n");
            ZFLAG = (dat == imm);
            if(ZFLAG)
		    printf("Zero flag set\n");
        }
        
        else
        {
            int imm32 = (int)imm;
            int dat = R[rn].getLowerData();
            if((dat > 0 && imm32 < 0 && (dat-imm32) < 0) || (dat < 0 && imm32 > 0 && (dat - imm32) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (dat < imm32);
            if(CFLAG)
		    	printf("Carry flag set\n");
		    	
            NFLAG = (dat < imm32);
            
            if(NFLAG)
		    	printf("Negative flag set\n");
		    	
            ZFLAG = (dat == imm32);
            if(ZFLAG)
		    	printf("Zero flag set\n");
        }
    }
    else if(mod == 11)  //extended or register
    {
	printf("[log] - CMP extended/register\n");
        int inst_t = IR.getLowerData() & 0x00200000;
        if(inst_t) //register
        {
            int rm = (IR.getLowerData() & 0x001f0000) >> 16;
            int imm6 = (IR.getLowerData() & 0x0000fc00) >> 10;
            if(sf)  //64 bit registers
            {
                if(shift == 0) //LSL
                {
                    uint64_t rn_data = R[rn].getData();
                    uint64_t rm_data = R[rm].getData();
                    rm_data = rm_data << imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
        if(OFLAG)
		    printf("Overflow flag set\n");
		    
            CFLAG = (rn_data < rm_data);
	    if(CFLAG)
		    printf("Carry flag set\n");
		    
            NFLAG = (rn_data < rm_data);
	    if(NFLAG)
		    printf("Negative flag set\n");
		    
            ZFLAG = (rn_data == rm_data);
        if(ZFLAG)
		    printf("Zero flag set\n");
        
                }
                
                else if(shift == 1 or shift == 2) // LSR or ASR(in c both are same)
                {
                    uint64_t rn_data = R[rn].getData();
                    uint64_t rm_data = R[rm].getData();
                    rm_data = rm_data >> imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            if(OFLAG)
		    printf("Overflow flag set\n");
            CFLAG = (rn_data < rm_data);
		if(CFLAG)
		    printf("Carry flag set\n");

            NFLAG = (rn_data < rm_data);
		if(NFLAG)
		    printf("Negative flag set\n");

            ZFLAG = (rn_data == rm_data);
		if(ZFLAG)
		    printf("Zero flag set\n");

                }
            }
            
            else    //32 bit registers
            {
                if(shift == 0) //LSL
                {
                    uint32_t rn_data = R[rn].getLowerData();
                    uint32_t rm_data = R[rm].getLowerData();
                    rm_data = rm_data << imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            
            CFLAG = (rn_data < rm_data);
            NFLAG = (rn_data < rm_data);
            ZFLAG = (rn_data == rm_data);
            if(NFLAG)
		    printf("Negative flag set\n");
		    if(CFLAG)
		    printf("Carry flag set\n");
		    if(ZFLAG)
		    printf("Zero flag set\n");
		    if(OFLAG)
		    printf("Overflow flag set\n");
                }
                
                else if(shift == 1 or shift == 2) // LSR or ASR(in c both are same)
                {
                    uint32_t rn_data = R[rn].getLowerData();
                    uint32_t rm_data = R[rm].getLowerData();
                    rm_data = rm_data >> imm6;
                    
                    if((rn_data > 0 && rm_data < 0 && (rn_data-rm_data) < 0) || (rn_data < 0 && rm_data > 0 && (rn_data - rm_data) > 0))
                OFLAG = true;
            
            CFLAG = (rn_data < rm_data);
            NFLAG = (rn_data < rm_data);
            ZFLAG = (rn_data == rm_data);
            
            if(CFLAG)
		    printf("Carry flag set\n");
		    if(NFLAG)
		    printf("Negative flag set\n");
		    if(ZFLAG)
		    printf("Zero flag set\n");
		    if(OFLAG)
		    printf("Overflow flag set\n");
                }
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
leaq 0x4653(%rip), %rdi      # 0x65f0
callq 0x1140
leaq 0x18247(%rip), %r12     # 0x1a1f0
movq %r12, %rdi
callq 0x5c8a
movl %eax, %ebx
movq %r12, %rdi
callq 0x5c8a
movq %r12, %rdi
callq 0x5c8a
movq %r12, %rdi
callq 0x5c8a
movl %eax, %r14d
shrl $0x16, %r14d
andl $0x3, %r14d
movq %r12, %rdi
callq 0x5c8a
movl %eax, %ebp
movq %r12, %rdi
callq 0x5c8a
movl %eax, %r13d
shrl $0x18, %r13d
andl $0x1f, %r13d
movq %r12, %rdi
callq 0x5c8a
movl %eax, %r15d
shrl $0x5, %r15d
andl $0x1f, %r15d
movq %r12, %rdi
callq 0x5c8a
cmpl $0xb, %r13d
je 0x20b2
cmpl $0x11, %r13d
jne 0x2373
shrl $0xa, %ebp
andl $0xfff, %ebp            # imm = 0xFFF
leaq 0x45f4(%rip), %rdi      # 0x6626
callq 0x1140
movl %ebp, %r12d
shll $0xc, %r12d
cmpl $0x1, %r14d
cmovnel %ebp, %r12d
btl $0x1f, %ebx
movl %r15d, %eax
leaq 0x809c(%rip), %rcx      # 0xa0f0
leaq (%rcx,%rax,8), %rdi
jb 0x21a1
callq 0x5c8a
movl %eax, %ebx
cmpb $0x1, 0x8076(%rip)      # 0xa0e2
jne 0x207a
leaq 0x45db(%rip), %rdi      # 0x6650
callq 0x1140
cmpl %r12d, %ebx
setl %bpl
setl 0x805c(%rip)            # 0xa0e4
jge 0x21ef
leaq 0x45ed(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x8042(%rip)      # 0xa0e3
leaq 0x46c7(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x21f6
leaq 0x454f(%rip), %rdi      # 0x6608
callq 0x1140
leaq 0x1812b(%rip), %rdi     # 0x1a1f0
callq 0x5c8a
btl $0x15, %eax
jae 0x2373
leaq 0x18115(%rip), %r13     # 0x1a1f0
movq %r13, %rdi
callq 0x5c8a
movl %eax, %r12d
shrl $0x10, %r12d
andl $0x1f, %r12d
movq %r13, %rdi
callq 0x5c8a
movl %eax, %ebp
shrl $0xa, %ebp
andl $0x3f, %ebp
btl $0x1f, %ebx
jb 0x220d
cmpl $0x3, %r14d
je 0x2373
movl %r15d, %eax
testl %r14d, %r14d
jne 0x224f
leaq 0x7fcb(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5c8a
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5c8a
movl %ebp, %ecx
shll %cl, %eax
cmpl %eax, %ebx
setb 0x7f9b(%rip)            # 0xa0e4
setb 0x7f93(%rip)            # 0xa0e3
sete 0x7f8a(%rip)            # 0xa0e1
jae 0x2165
leaq 0x460f(%rip), %rdi      # 0x676f
callq 0x1140
cmpb $0x1, 0x7f78(%rip)      # 0xa0e4
jne 0x217a
leaq 0x450d(%rip), %rdi      # 0x6682
callq 0x1140
cmpb $0x1, 0x7f60(%rip)      # 0xa0e1
jne 0x218f
leaq 0x45cf(%rip), %rdi      # 0x6759
callq 0x1140
cmpb $0x0, 0x7f4c(%rip)      # 0xa0e2
jne 0x22cd
jmp 0x2373
callq 0x5c86
movq %rax, %rbx
cmpb $0x1, 0x7f32(%rip)      # 0xa0e2
jne 0x21be
leaq 0x4497(%rip), %rdi      # 0x6650
callq 0x1140
cmpq %r12, %rbx
setb %bpl
setb 0x7f18(%rip)            # 0xa0e4
jae 0x21fe
leaq 0x44ad(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x7f02(%rip)      # 0xa0e3
leaq 0x4587(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x2205
movb %bpl, 0x7eed(%rip)      # 0xa0e3
cmpl %r12d, %ebx
jmp 0x2350
movb %bpl, 0x7ede(%rip)      # 0xa0e3
cmpq %r12, %rbx
jmp 0x2350
cmpl $0x3, %r14d
je 0x2373
movl %r15d, %eax
testl %r14d, %r14d
jne 0x22d9
leaq 0x7ec6(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5c86
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5c86
movq %rax, %r14
movl %ebp, %ecx
shlq %cl, %r14
jmp 0x2300
leaq 0x7e9a(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5c8a
movl %eax, %ebx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5c8a
movl %ebp, %ecx
shrl %cl, %eax
cmpl %eax, %ebx
setb 0x7e6a(%rip)            # 0xa0e4
setb 0x7e62(%rip)            # 0xa0e3
sete 0x7e59(%rip)            # 0xa0e1
jae 0x2296
leaq 0x43f1(%rip), %rdi      # 0x6682
callq 0x1140
cmpb $0x1, 0x7e46(%rip)      # 0xa0e3
jne 0x22ab
leaq 0x44c9(%rip), %rdi      # 0x676f
callq 0x1140
cmpb $0x1, 0x7e2f(%rip)      # 0xa0e1
jne 0x22c0
leaq 0x449e(%rip), %rdi      # 0x6759
callq 0x1140
cmpb $0x1, 0x7e1b(%rip)      # 0xa0e2
jne 0x2373
leaq 0x437c(%rip), %rdi      # 0x6650
jmp 0x2360
leaq 0x7e10(%rip), %r14      # 0xa0f0
leaq (%r14,%rax,8), %rdi
callq 0x5c86
movq %rax, %rbx
movl %r12d, %eax
leaq (%r14,%rax,8), %rdi
callq 0x5c86
movq %rax, %r14
movl %ebp, %ecx
shrq %cl, %r14
cmpb $0x1, 0x7ddb(%rip)      # 0xa0e2
jne 0x2315
leaq 0x4340(%rip), %rdi      # 0x6650
callq 0x1140
cmpq %r14, %rbx
setb %bpl
setb 0x7dc1(%rip)            # 0xa0e4
jae 0x2346
leaq 0x4356(%rip), %rdi      # 0x6682
callq 0x1140
movb %bpl, 0x7dab(%rip)      # 0xa0e3
leaq 0x4430(%rip), %rdi      # 0x676f
callq 0x1140
jmp 0x234d
movb %bpl, 0x7d96(%rip)      # 0xa0e3
cmpq %r14, %rbx
sete 0x7d8a(%rip)            # 0xa0e1
jne 0x2373
leaq 0x43f9(%rip), %rdi      # 0x6759
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1140
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq